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

Angular表格汇总行触发ExpressionChangedAfterItHasBeenCheckedError求助

PrimeNG树表格动态汇总行的ExpressionChangedAfterItHasBeenCheckedError问题

需求

为带筛选功能的PrimeNG树表格实现汇总行,要求仅统计当前视图内的数据,汇总结果需随树展开/折叠、筛选操作动态更新。

当前实现方案

  • 将summaryFunction作为元素属性[attr.summaryFunction]绑定到表格单元格,在渲染每行数据时累加计算汇总值
  • 在ngDoCheck钩子中重置summaryMap,避免重复累加(尝试ngOnInit/ngOnViewInit/ngOnChanges均无法正确重置,会导致汇总值重复累加错误)

遇到的问题

功能运行正常,但浏览器针对每列触发三次ExpressionChangedAfterItHasBeenCheckedError错误。

尝试过的无效修复方法

  • 更换生命周期钩子:导致汇总值计算错误
  • 在summaryFunction中添加cd.detectChanges():触发无限循环
  • 用setTimeout包裹判断逻辑:触发无限循环
  • 用Promise.resolve().then包裹判断逻辑:触发无限循环

需要解决的问题

  1. 消除ExpressionChangedAfterItHasBeenCheckedError错误
  2. 理解上述常规修复方法引发无限循环的原因

TypeScript代码

export class PrimetreeComponent implements OnInit, DoCheck {
  sampleData: TreeNode[] = []
  columns: any[] = [];
  summaryMap = new Map();
  columnIndex = 0;

  constructor(private nodeService: NodeService, private cd: ChangeDetectorRef) {}


  ngOnInit(): void {
    this.nodeService.getFilesystem().subscribe(data => {this.sampleData = data});

      this.columns = [
      {field: 'name', header: 'name'},
      {field: 'size', header: 'size'},
      {field: 'type', header: 'type'}]
  }

 ngDoCheck(): void {
  this.summaryMap = new Map();
 }

  summaryFunction(columnIndex:number, rowData:any){
    
    if(this.summaryMap.has(columnIndex)){
      //如果行数据是数字则累加,否则统计行数
      if(Number(rowData)){
        this.summaryMap.set(columnIndex, this.summaryMap.get(columnIndex)+Number(rowData));
      } else {
        this.summaryMap.set(columnIndex, this.summaryMap.get(columnIndex)+1)
      }
    } else {
      if(Number(rowData)){
        this.summaryMap.set(columnIndex, Number(rowData));
      } else {
        this.summaryMap.set(columnIndex, 1)
      }
    } 
  }
}

HTML模板代码

<p-treeTable #tt [value]="sampleData" [columns]="columns">
  <ng-template pTemplate="caption">
    <div style="text-align: right">
      <span class="p-input-icon-left">
        <i class="pi pi-search"></i>
        <input
          pInputText
          type="text"
          size="50"
          placeholder="Global Filter"
          (input)="tt.filterGlobal($any($event.target).value, 'contains')"
          style="width:auto"
        />
      </span>
    </div>
  </ng-template>
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        {{ col.header }}
      </th>
    </tr>
    <tr>
      <th *ngFor="let col of columns">
        <input
          pInputText
          type="text"
          class="w-full"
          (input)="
            tt.filter($any($event.target).value, col.field, col.filterMatchMode)
          "
        />
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowNode let-rowData="rowData" >
    <tr>
      <td *ngFor="let col of columns; let i = index;" [attr.summaryFunction]="summaryFunction(i,rowData[col.field])">
        <p-treeTableToggler
          [rowNode]="rowNode"
          *ngIf="i == 0"
          (columnIndex)="i"
        ></p-treeTableToggler>
        {{ rowData[col.field] }}
      </td>
    </tr>
  </ng-template>
  <ng-template pTemplate="emptymessage">
    <tr>
      <td [attr.colspan]="columns.length">No data found.</td>
    </tr>
  </ng-template>
<ng-template pTemplate="summary">
  <tr>
    <td *ngFor="let col of columns;  let i = index;">
      {{ col.header }}--sumMap--{{summaryMap.get(i) }}
    </td>
  </tr>
</ng-template>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:45:28