如何解决*ngFor生成的多mat-select全选功能仅第一列生效的问题
问题核心原因
你遇到的问题来自两个错误设计:
@ViewChild('mySel')默认只会匹配页面上第一个出现的#mySel引用元素,你循环生成了多列下拉框,全选逻辑永远只会作用到第一列的下拉框上- 全局共用的
allSelected、columnDropdownOptions变量没有和列绑定,多列操作会互相覆盖状态
修复方案
修改组件TS代码
export interface PeriodicElement { name: string; position: number; weight: number; symbol: string; } const ELEMENT_DATA: Array<PeriodicElement> = [ {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, ]; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { dataSource: Array<any>; // 按列存储下拉选项 columnOptionsMap: Record<string, any[]> = {}; // 按列存储全选状态 allSelectedMap: Record<string, boolean> = {}; constructor() { this.dataSource = ELEMENT_DATA; } displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; dropDown(column:string) { // 避免重复初始化 if (this.columnOptionsMap[column]) return; this.columnOptionsMap[column] = this.dataSource.map(row => row[column]); } toggleAllSelection(select: MatSelect, column: string) { this.allSelectedMap[column] = !this.allSelectedMap[column]; if (this.allSelectedMap[column]) { select.options.forEach((item : MatOption) => item.select()); } else { select.options.forEach((item : MatOption) => item.deselect()); } } }
修改模板代码
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8"> <ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column"> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ column }} <mat-select #mySel (click)="dropDown(column)" multiple> <mat-checkbox [checked]="allSelectedMap[column]" (click)="$event.stopPropagation(); toggleAllSelection(mySel, column)" style="padding-left: 17px;" > Select all </mat-checkbox> <mat-option *ngFor="let option of columnOptionsMap[column]" [value]="option">{{option}}</mat-option> </mat-select> </th> <td mat-cell *matCellDef="let element"> {{ element[column] }} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
改动说明
- 新增
$event.stopPropagation()避免点击全选框时触发展开/收起下拉框的冲突 - 下拉选项仅在第一次点击列下拉时初始化,避免重复计算
- 所有列的状态独立存储,不会互相干扰
内容的提问来源于stack exchange,提问作者Ainsley Morgan
相关产品推荐
相关产品推荐

