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

Angular隐藏mat-table触发actives of undefined错误如何解决

错误原因
  1. 核心报错Cannot read property 'actives' of undefined是因为MatMultiSortTableDataSource初始化时依赖的@ViewChild(MatMultiSort) sort实例未被正确获取:你将mat-table包裹在*ngIf条件渲染逻辑中,在setTimeout中初始化数据源时,Angular 变更检测尚未完成,mat-table上绑定的matMultiSort指令实例还未被@ViewChild查询到,sort为undefined传入数据源构造函数后,内部访问actives属性直接抛出异常。
  2. 现有条件渲染逻辑仅判断了table !== undefined,既不满足你要求的展示/隐藏规则,也没有覆盖table.dataSource未初始化完成的边界场景,会触发额外的运行时错误。
  3. 空实现的ngOnChanges生命周期未处理父组件传入的tableData、tableOptions更新场景,后续数据更新时会出现表格内容不同步的问题。
修复方案

TS 代码修改

首先补充生命周期实现、增加展示条件计算属性、补充各方法的非空判断:

import { AfterViewInit, SimpleChanges } from '@angular/core';

export class TableMultiSortComponent implements OnInit, OnChanges, AfterViewInit {
  @Input() tableOptions:any;
  @Input() tableMessage:any;
  @Input() tableData:any = [];
  test = 0;
  @Input() isClientSide:boolean = false;
  @Input() isLoading: boolean = false;
  @Output() tableActionsEvent = new EventEmitter<any>();
  @Output() dataServiceEvent = new EventEmitter<any>() ;
  @ViewChild(MatMultiSort, { static: false }) sort: MatMultiSort;
  hasInfoMessage: boolean;
  tableConfig: any = TABLE_MULTI_SORT_OPTIONS.DEFAULT;
  table:TableData<any>;
  displayedColumns: any;
  
  constructor() { }

  // 表格展示条件计算属性,完全匹配你的需求
  get showTable(): boolean {
    if (!this.table || !this.table.dataSource || !this.tableOptions) return false;
    const dataNotEmpty = this.table.dataSource.data?.length > 0;
    const notificationOff = !this.tableOptions.notifications;
    // 符合要求则展示
    if (dataNotEmpty && notificationOff) return true;
    // 符合要求则隐藏
    if (!dataNotEmpty && this.tableOptions.notifications) return false;
    // 其余情况正常展示
    return true;
  }

  ngOnChanges(changes: SimpleChanges): void {
    // 监听表格数据更新
    if (changes['tableData'] && this.table?.dataSource) {
      this.table.data = this.tableData;
    }
    // 监听表格配置更新,按需开启
    if (changes['tableOptions'] && !changes['tableOptions'].firstChange) {
      this.initTableMultiSort();
    }
  }

  ngOnInit(): void {   
    this.initTableMultiSort();
  }

  ngAfterViewInit(): void {
    // 确保sort实例存在后再初始化数据源,避免报错
    if (this.sort) {
      this.table.dataSource = new MatMultiSortTableDataSource(this.sort, this.isClientSide);
      this.getData();
    }
  }

  initTableMultiSort() {
    this.tableConfig = {
      ...this.tableConfig,
      ...this.tableOptions
    }
    
    this.table = new TableData<any>(this.tableConfig.columns,this.tableConfig.sortParams);
    this.table.pageSize = this.tableConfig.pageSize;
    this.table.pageIndex = this.tableConfig.pageIndex;
    this.table.nextObservable.subscribe(() => { this.getData(); });
    this.table.sortObservable.subscribe(() => { this.getData(); });
    this.table.previousObservable.subscribe(() => { this.getData(); });
    this.table.sizeObservable.subscribe(() => { this.getData(); });
  }

  getData(){
    this.table.totalElements = 1;
    this.table.pageIndex = 0;
    this.table.totalElements = 0;
    this.table.pageSize = 10;
    this.table.data = this.tableData;
    if(this.dataServiceEvent) {
      this.dataServiceEvent.emit(this.table);
    }
  }

  // 补充非空判断,避免查询列不存在时报错
  getColumnSubtitle(id) :string{    
    return this.tableOptions?.columns?.find(c => c.id === id)?.subtitle || '';
  }

  getColumnSubId(id) :string{
    return this.tableOptions?.columns?.find(c => c.id === id)?.subId || '';
  }

  getActions(id):any{
    return this.tableOptions?.columns?.find(c => c.id === id)?.actions || [];
  }
}

HTML 代码修改

替换原有条件渲染逻辑,增加数据源非空判断:

<mat-card *ngIf="showTable">
  <div style="padding-top: 12px;" *ngIf="tableOptions.notifications">
    <div class="alertInfo" >
      <mat-icon>{{tableOptions.notifications[0].type}}</mat-icon>{{tableOptions.notifications[0].message}}
    </div>
  </div>
  <!-- 确保数据源初始化完成后再渲染表格 -->
  <mat-table *ngIf="table.dataSource" mat-table [dataSource]="table.dataSource" matMultiSort (matSortChange)="table.onSortEvent()"> 
    <ng-container *ngFor="let column of table.columns" [matColumnDef]="column.id">
      <mat-header-cell class="table-multi-sort-header" *matHeaderCellDef [mat-multi-sort-header]="column.id"> 
        <div>{{column.name}}</div> 
        <div class="sub-text">{{getColumnSubtitle(column.id)}}</div>
      </mat-header-cell>
      <mat-cell *matCellDef="let row">
          <ng-container *ngIf="column.id !== 'action'; then col; else actionCol"></ng-container>
          <ng-template #col>
            <app-table-multi-sort-cell-default [cellData]="row" [id]="column.id" [subId]="getColumnSubId(column.id)"></app-table-multi-sort-cell-default>
          </ng-template>
          <ng-template #actionCol>
            <app-table-multi-sort-cell-action [rowData]="row" [actions]="getActions(column.id)" (actionClickEvent)="clickTableAction($event,row)"></app-table-multi-sort-cell-action>
          </ng-template>
      </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="table.displayedColumns; sticky:true"></mat-header-row>
    <mat-row *matRowDef="let item; columns: table.displayedColumns;"></mat-row>
  </mat-table> 
  <mat-progress-bar *ngIf="isLoading" mode="indeterminate"></mat-progress-bar>
</mat-card>

内容的提问来源于stack exchange,提问作者Rajiv Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:21:01