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

Angular Material如何渲染多层嵌套对象内的数组数据到表格

核心问题

你当前的代码有三处核心错误导致嵌套数据无法渲染:

  • 模型定义和接口返回不匹配:你在Month类中把compteurFDP/prisesDuMois/compteurFinDuMois定义为数组,但db.json里返回的是单个对象,调用.length会直接返回undefined,遍历逻辑全失效
  • 数据展平逻辑错误:你当前的reduce逻辑没有把每个月份下的三类子数据(期初、当月消耗、期末)和列对应上,导致单元格取不到值
  • 表头列定义不匹配:你要实现的是月份下分三类子指标的多层表头,当前的列定义没有对应这三层结构,和你写的colspan分组也对不上

修复步骤

第一步:修正模型定义

把Month类里的数组类型改成单个对象,和接口返回对齐:

export class Month {
  month!: string;
  compteurFDP!: compteurFDP; // 去掉Array声明,改为单个对象
  prisesDuMois!: prisesDuMois;
  compteurFinDuMois!: compteurFinDuMois;
}

第二步:修正TS中的数据处理逻辑

把原来错误的reduce逻辑替换成按月份+指标类型拼接列名的展平逻辑,同时补全所有显示列:

// 定义每个月份下要显示的三类指标映射规则
const MONTH_SUB_KEYS = [
  {suffix: '_fdp_cp', label: 'CP', group: 'Cpteur FDP'},
  {suffix: '_fdp_rtts', label: 'RTTS', group: 'Cpteur FDP'},
  {suffix: '_fdp_rtte', label: 'RTTE', group: 'Cpteur FDP'},
  {suffix: '_prise_cp', label: 'CP', group: 'Prises du mois'},
  {suffix: '_prise_rtts', label: 'RTTS', group: 'Prises du mois'},
  {suffix: '_prise_rtte', label: 'RTTE', group: 'Prises du mois'},
  {suffix: '_fin_cp', label: 'CP', group: 'Cpteur fin de mois'},
  {suffix: '_fin_rtts', label: 'RTTS', group: 'Cpteur fin de mois'},
  {suffix: '_fin_rtte', label: 'RTTE', group: 'Cpteur fin de mois'},
  {suffix: '_fin_somme', label: 'Somme', group: 'Cpteur fin de mois'},
]

displayedColumns: string[] = [
  'collaborator',
  'cetCP',
  'cetRTT',
  'perteRTT',
  'perteCP'
];
// 存储所有动态生成的月份子列配置
monthSubColumns: {colKey: string, month: string, label: string, group: string}[] = [];

ngOnInit(): void {
  this.reportingService.getNews().subscribe(
    (response: visionCompacteDTOs[]) => {
      if (!response) return;
      // 生成所有月份子列配置
      const months = response[0].mnth;
      months.forEach(m => {
        MONTH_SUB_KEYS.forEach(k => {
          const colKey = `${m.month}${k.suffix}`;
          this.monthSubColumns.push({
            colKey,
            month: m.month,
            label: k.label,
            group: k.group
          })
          this.displayedColumns.push(colKey);
        })
      })
      // 展平嵌套数据,和列名一一对应
      this.dataSource = response.map(data => {
        const flatObj: any = {...data};
        data.mnth.forEach(m => {
          // 赋值期初值
          flatObj[`${m.month}_fdp_cp`] = m.compteurFDP.cp;
          flatObj[`${m.month}_fdp_rtts`] = m.compteurFDP.rtts;
          flatObj[`${m.month}_fdp_rtte`] = m.compteurFDP.rtte;
          // 赋值当月消耗值
          flatObj[`${m.month}_prise_cp`] = m.prisesDuMois.cp;
          flatObj[`${m.month}_prise_rtts`] = m.prisesDuMois.rtts;
          flatObj[`${m.month}_prise_rtte`] = m.prisesDuMois.rtte;
          // 赋值期末值
          flatObj[`${m.month}_fin_cp`] = m.compteurFinDuMois.cp;
          flatObj[`${m.month}_fin_rtts`] = m.compteurFinDuMois.rtts;
          flatObj[`${m.month}_fin_rtte`] = m.compteurFinDuMois.rtte;
          flatObj[`${m.month}_fin_somme`] = m.compteurFinDuMois.somme;
        })
        return flatObj;
      })
    },
    error => console.log('Error Occured: ' + error)
  );
}

第三步:修正HTML渲染逻辑

按多层表头结构渲染,可根据你需要的层级调整colspan分组逻辑:

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 lftm">
  <!-- 固定列定义 -->
  <ng-container matColumnDef="collaborator">
    <th mat-header-cell *matHeaderCellDef> 员工 </th>
    <td mat-cell *matCellDef="let element"> {{element.collaborator}} </td>
  </ng-container>
  <ng-container matColumnDef="cetCP">
    <th mat-header-cell *matHeaderCellDef > CP </th>
    <td mat-cell *matCellDef="let element"> {{element.cetCP}} </td>
  </ng-container>
  <ng-container matColumnDef="cetRTT">
    <th mat-header-cell *matHeaderCellDef > RTT </th>
    <td mat-cell *matCellDef="let element"> {{element.cetRTT}} </td>
  </ng-container>
  <ng-container matColumnDef="perteRTT">
    <th mat-header-cell *matHeaderCellDef > 损失RTT </th>
    <td mat-cell *matCellDef="let element"> {{element.perteRTT}} </td>
  </ng-container>
  <ng-container matColumnDef="perteCP">
    <th mat-header-cell *matHeaderCellDef> 损失CP </th>
    <td mat-cell *matCellDef="let element"> {{element.perteCP}} </td>
  </ng-container>

  <!-- 动态生成月份子列定义 -->
  <ng-container *ngFor="let col of monthSubColumns" [matColumnDef]="col.colKey">
    <th mat-header-cell *matHeaderCellDef> {{col.label}} </th>
    <td mat-cell *matCellDef="let element"> {{element[col.colKey]}} </td>
  </ng-container>

  <!-- 多层表头+内容行定义 -->
  <tr mat-header-row *matHeaderRowDef="['collaborator', 'cetCP', 'cetRTT', 'perteRTT', 'perteCP', ...monthSubColumns.map(c=>c.colKey)]"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 22:54:04