如何阻止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
相关产品推荐
相关产品推荐

