Angular隐藏mat-table触发actives of undefined错误如何解决
错误原因
- 核心报错
Cannot read property 'actives' of undefined是因为MatMultiSortTableDataSource初始化时依赖的@ViewChild(MatMultiSort) sort实例未被正确获取:你将mat-table包裹在*ngIf条件渲染逻辑中,在setTimeout中初始化数据源时,Angular 变更检测尚未完成,mat-table上绑定的matMultiSort指令实例还未被@ViewChild查询到,sort为undefined传入数据源构造函数后,内部访问actives属性直接抛出异常。 - 现有条件渲染逻辑仅判断了
table !== undefined,既不满足你要求的展示/隐藏规则,也没有覆盖table.dataSource未初始化完成的边界场景,会触发额外的运行时错误。 - 空实现的
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
相关产品推荐
相关产品推荐

