You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止Angular Material 11动态mat-table中的mat-select关闭

解决Angular Material表格动态列切换时Mat-Select自动关闭的问题

问题根源在于:修改_displayedColumns触发表格列重绘时,承载Mat-Select的表头元素会被Angular销毁并重新创建,导致下拉框失去当前打开状态。下面提供两种可行的解决方案:

方案一:使用trackBy函数减少不必要的DOM重建

通过给*ngFor添加trackBy,让Angular仅针对新增/删除的列进行DOM操作,已存在的列(包括包含Mat-Select的列)会保留原有DOM元素,从而维持下拉框的打开状态。

步骤1:在组件类中定义trackBy函数

trackColumn(index: number, column: string): string {
  // 以列名作为唯一标识,确保相同列名的元素不会被重复渲染
  return column;
}

步骤2:在模板的*ngFor中添加trackBy

<table
  mat-table
  [dataSource]="dataSource"
  matSort>
  <!-- 给*ngFor添加trackBy绑定 -->
  <ng-container
    *ngFor="let column of _displayedColumns; trackBy: trackColumn"
    [matColumnDef]="column">
    <th
      mat-header-cell
      *matHeaderCellDef>
      <mat-select
        [formControl]="columnsSelector"
        multiple
        class="column-show-selector"
        (selectionChange)="columnChange($event)">               
        <mat-option
          *ngFor="let menuItem of matMenuItems"
          [value]="menuItem">
          {{ menuItem }}
        </mat-option>
      </mat-select>
    </th>
    <!-- 剩余表格代码 -->
  </ng-container>
</table>

方案二:将列选择器与动态列分离渲染

把包含Mat-Select的列单独定义,不参与动态列的*ngFor循环,确保它的DOM元素始终存在,不受动态列变化影响。

步骤1:单独定义列选择器的列

<table
  mat-table
  [dataSource]="dataSource"
  matSort>
  <!-- 单独定义列选择器的列,不参与动态循环 -->
  <ng-container matColumnDef="columnsSelector">
    <th mat-header-cell *matHeaderCellDef>
      <mat-select
        [formControl]="columnsSelector"
        multiple
        class="column-show-selector"
        (selectionChange)="columnChange($event)">               
        <mat-option
          *ngFor="let menuItem of matMenuItems"
          [value]="menuItem">
          {{ menuItem }}
        </mat-option>
      </mat-select>
    </th>
    <td mat-cell *matCellDef="let element"></td> <!-- 数据行对应单元格可留空 -->
  </ng-container>

  <!-- 动态列的循环 -->
  <ng-container
    *ngFor="let column of _displayedColumns"
    [matColumnDef]="column">
    <!-- 你的动态列表头和单元格代码 -->
    <th mat-header-cell *matHeaderCellDef>{{ column }}</th>
    <td mat-cell *matCellDef="let element">{{ element[column] }}</td>
  </ng-container>

  <!-- 表头行:合并动态列和选择器列 -->
  <tr mat-header-row *matHeaderRowDef="[..._displayedColumns, 'columnsSelector']"></tr>
  <!-- 数据行:对应表头结构 -->
  <tr mat-row *matRowDef="let row; columns: [..._displayedColumns, 'columnsSelector']"></tr>
</table>

步骤2:简化columnChange函数

不需要再手动插入columnsSelector到列数组中:

columnChange(e: any) {
  this._displayedColumns = e.value;
}

两种方案都能实现列筛选功能,同时让Mat-Select保持打开状态,直到用户点击外部区域关闭。

内容的提问来源于stack exchange,提问作者Julio Rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 13:30:29