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

如何解决*ngFor生成的多mat-select全选功能仅第一列生效的问题

问题核心原因

你遇到的问题来自两个错误设计:

  1. @ViewChild('mySel') 默认只会匹配页面上第一个出现的#mySel引用元素,你循环生成了多列下拉框,全选逻辑永远只会作用到第一列的下拉框上
  2. 全局共用的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:45:03