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

多标签页表格排序时ngAfterViewInit未触发,matSort失效求助

MatSort在Angular标签页组件中无法正常工作

问题场景

现有三个组件:主组件approve-home和两个标签页组件approve-main、approve-group。切换到第二个标签页approve-group后,表格的matSort功能完全失效,点击排序表头无任何反应。排查发现ngAfterViewInit仅在组件首次启动时触发,触发时间早于切换到该标签页的操作。

相关代码

approve-home.component.ts

@Component({
  selector: 'app-approve-home',
  templateUrl: './approve-home.component.html',
  styleUrls: ['./approve-home.component.css']
})
export class ApproveHomeComponent implements OnInit {

  @ViewChild('tabGroup', {static: false}) tabGroup: MatTabGroup;

  constructor() {
  }

  ngOnInit() {
  }

  onMoveTab(event: { tabIndex: number }) {
    this.tabGroup.selectedIndex = event.tabIndex;
  }

}

approve-home.component.html

<mat-tab-group #tabGroup class="tab-hide">
      <mat-tab label="To be hidden">
        <app-approve-main (moveTab)="onMoveTab($event)"></app-approve-main>
      </mat-tab>
      <mat-tab label="To be hidden">
        <app-approve-group (moveTab)="onMoveTab($event)"></app-approve-group>
      </mat-tab>
    </mat-tab-group>

approve-group.component.ts

displayedColumns: string[] = ['applicationNo', 'surname', 'otherNames', 'dob', 'tdType', 'previousTDNo', 'action'];
dataSource = new MatTableDataSource<TdApplication>([]);

@ViewChild(MatSort, {static: true}) sort: MatSort;
@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
@Output() moveTab = new EventEmitter<{ tabIndex: number }>();

ngAfterViewInit(): void {
  this.dataSource.sortingDataAccessor = (tdApps, property) => {
    switch (property) {
      case 'applicationNo':
        console.log(property);
        return tdApps.applicationNo ? tdApps.applicationNo.toLocaleLowerCase() : '';
      case 'surname':
        return tdApps.applicantDetails.surname.toLocaleLowerCase();
      case 'otherNames':
        return tdApps.applicantDetails.otherName.toLocaleLowerCase();
      case 'dob':
        return tdApps.applicantDetails.dob.toString();
      case 'tdType':
        return tdApps.applicantDetails.tdType && tdApps.applicantDetails.tdType.documentType ? tdApps.applicantDetails.tdType.documentType.name.toLocaleLowerCase() : '';
      case 'previousTDNo':
        return tdApps.applicantDetails.prevTdNo && tdApps.applicantDetails.prevTdNo.length > 0 ? tdApps.applicantDetails.prevTdNo.toLocaleLowerCase() : '';
      default:
        // @ts-ignore
        return tdApps[property];
    }
  };
  this.dataSource.sort = this.sort;
}

approve-group.component.html

<table mat-table [dataSource]="dataSource"  class="mat-elevation-z8" matSort>

      <!-- Application No Column -->
      <ng-container matColumnDef="applicationNo">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> Application No </th>
        <td mat-cell *matCellDef="let element"> {{element?.applicationNo}} </td>
      </ng-container>

注意:所有导入均已正确配置

问题原因

  1. MatTabGroup的DOM渲染特性:未激活的标签页内容会被设置为display: none,虽然组件已初始化,但MatSort的交互事件未正确绑定到数据源,导致点击表头无响应。
  2. static属性设置问题:@ViewChild(MatSort, {static: true})会在组件初始化早期获取实例,此时标签页DOM尚未完全渲染,导致sort实例与数据源的关联失效。

解决方案

方案1:调整MatSort的ViewChild获取方式

将static: true改为static: false,确保在视图完全渲染后获取MatSort实例:

@ViewChild(MatSort, {static: false}) sort: MatSort;

方案2:监听标签页激活事件,重新绑定Sort

在主组件中监听标签页切换事件,当切换到目标标签页时,通知子组件重新绑定Sort:

  1. 修改approve-home.component.html,添加标签切换事件:
<mat-tab-group #tabGroup class="tab-hide" (selectedTabChange)="onTabChange($event)">
  <!-- 原有标签内容不变 -->
</mat-tab-group>
  1. 在approve-home.component.ts中添加事件处理逻辑:
import { ApproveGroupComponent } from './approve-group/approve-group.component';

// ...

@ViewChild(ApproveGroupComponent) approveGroup: ApproveGroupComponent;

onTabChange(event: MatTabChangeEvent) {
  // 第二个标签页的索引为1,根据实际情况调整
  if (event.index === 1) {
    this.approveGroup.rebindSort();
  }
}
  1. 在approve-group.component.ts中添加rebindSort方法:
rebindSort() {
  this.dataSource.sort = this.sort;
  // 手动触发数据源更新,确保排序逻辑生效
  this.dataSource._updateChangeSubscription();
}

方案3:启用标签页懒加载

给目标标签页添加lazyLoad属性,确保组件在首次激活时才初始化,此时ngAfterViewInit会在标签页显示后执行:

<mat-tab label="To be hidden" lazyLoad>
  <app-approve-group (moveTab)="onMoveTab($event)"></app-approve-group>
</mat-tab>

验证

完成上述任意一种修改后,切换到第二个标签页,点击排序表头,控制台应输出对应的property值,表格数据会按指定规则排序。

内容的提问来源于stack exchange,提问作者Ashrik Ahamed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:45:49