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

使用ng-template在cdk-virtual-scroll-viewport中渲染mat-table报错求助

问题:ng-template结合cdk-virtual-scroll-viewport渲染mat-table报错

报错信息

ERROR TypeError: Cannot read properties of undefined (reading '_switchDataSource')
at TableItemSizeDirective.ngAfterContentInit (ng-table-virtual-scroll.mjs:186:40)

当前代码结构

<cdk-virtual-scroll-viewport tvsItemSize [footerEnabled]="true"
                             [headerEnabled]="false">
    <ng-container *ngTemplateOutlet="operationTable;context:{$implicit:operationTableDataSource}">
    </ng-container>
</cdk-virtual-scroll-viewport>

<ng-template #operationTable>
    <mat-table>
        .....
    </mat-table>
</ng-template>

正常运行的代码(不使用ng-template)

<cdk-virtual-scroll-viewport tvsItemSize [footerEnabled]="true"
                             [headerEnabled]="false">
    <mat-table>
        .....
    </mat-table>
</cdk-virtual-scroll-viewport>

问题原因与解决方案

这个错误源于ng-table-virtual-scroll的TableItemSizeDirective在ngAfterContentInit钩子执行时,会尝试获取viewport内部的mat-table实例,但ngTemplateOutlet属于延迟渲染逻辑——当指令初始化时,mat-table还未被插入到viewport的DOM树中,导致指令找不到table实例,进而调用_switchDataSource时出现undefined错误。

方案1:替换ngTemplateOutlet为ngIf(推荐)

若仅需复用或条件渲染table,用*ngIf替代ngTemplateOutlet,确保table在viewport初始化时就能被指令检测到:

<cdk-virtual-scroll-viewport tvsItemSize [footerEnabled]="true"
                             [headerEnabled]="false">
    <mat-table *ngIf="operationTableDataSource" [dataSource]="operationTableDataSource">
        .....
    </mat-table>
</cdk-virtual-scroll-viewport>

方案2:手动触发指令初始化逻辑(需依赖库内部实现)

如果必须使用ngTemplateOutlet,可以通过ViewChild获取指令实例,在模板渲染完成后手动触发初始化:

  1. 组件内添加逻辑:
import { ViewChild, AfterViewInit } from '@angular/core';
import { TableItemSizeDirective } from 'ng-table-virtual-scroll';

@Component({...})
export class YourComponent implements AfterViewInit {
  @ViewChild(TableItemSizeDirective) tableItemSizeDir!: TableItemSizeDirective;

  ngAfterViewInit() {
    // 延迟执行确保模板渲染完成
    setTimeout(() => {
      this.tableItemSizeDir?.ngAfterContentInit();
    });
  }
}
  1. 保留原模板结构不变

方案3:调整内容投影时机

将ng-template内容直接嵌套在viewport内的ng-container中,同时确保数据源在viewport初始化前已准备好:

<cdk-virtual-scroll-viewport tvsItemSize [footerEnabled]="true"
                             [headerEnabled]="false">
    <ng-container>
        <mat-table [dataSource]="operationTableDataSource">
            .....
        </mat-table>
    </ng-container>
</cdk-virtual-scroll-viewport>

总结

这不属于cdk-virtual-scroll的功能限制,而是ng-table-virtual-scroll库的指令对内容渲染时机有依赖——要求mat-table在指令的ngAfterContentInit钩子执行时已存在于viewport的内容投影中。ngTemplateOutlet的延迟渲染特性打破了这个依赖关系,从而引发报错。

内容的提问来源于stack exchange,提问作者Amit Chigadani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:35:51