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

如何基于接口数据用Angular Material创建动态双表头表格?

问题描述

想要创建如下所示的带动态详情列的表格:

Level663
QuestionCommentCommentComment
Q15 - 67 - 10
Q210 - 2021 - 30
Q320 - 30

接口返回的数据格式如下:

[
  {
    'level' : 6,
    'Question' : 'Q1',
    'low' : 5,
    'high' : 6
  },
  {
    'level' : 6,
    'Question' : 'Q1',
    'low' : 7,
    'high' : 10
  },
  {
    'level' : 6,
    'Question' : 'Q2',
    'low' : 10,
    'high' : 20
  },
  {
    'level' : 6,
    'Question' : 'Q2',
    'low' : 21,
    'high' : 30
  },
  {
    'level' : 3,
    'Question' : 'Q3',
    'low' : 20,
    'high' : 30
  }
]

请问如何在Angular Material表格(mat table)中根据返回的数据实现上述带有动态列(如6、3等)的表格?


实现步骤

1. 数据预处理

首先需要把接口返回的扁平数据转换成适合表格展示的结构化数据,同时保留重复的level列(比如表格里的两个6列)。在组件的TypeScript代码中处理:

import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';

interface RawData {
  level: number;
  Question: string;
  low: number;
  high: number;
}

interface TableData {
  question: string;
  comments: { [key: string]: string };
}

@Component({
  selector: 'app-dynamic-table',
  templateUrl: './dynamic-table.component.html',
  styleUrls: ['./dynamic-table.component.css']
})
export class DynamicTableComponent implements OnInit {
  rawData: RawData[] = []; // 后续替换为接口返回数据
  displayedColumns: string[] = ['question'];
  dynamicColumns: { id: string, label: string }[] = [];
  dataSource = new MatTableDataSource<TableData>([]);

  ngOnInit(): void {
    // 模拟接口请求,实际项目替换为HTTP请求
    this.rawData = [
      { level: 6, Question: 'Q1', low: 5, high: 6 },
      { level: 6, Question: 'Q1', low: 7, high: 10 },
      { level: 6, Question: 'Q2', low: 10, high: 20 },
      { level: 6, Question: 'Q2', low: 21, high: 30 },
      { level: 3, Question: 'Q3', low: 20, high: 30 }
    ];
    this.processData();
  }

  private processData(): void {
    // 按问题分组,收集每个问题的所有区间数据
    const questionGroups = new Map<string, RawData[]>();
    this.rawData.forEach(item => {
      if (!questionGroups.has(item.Question)) {
        questionGroups.set(item.Question, []);
      }
      questionGroups.get(item.Question)?.push(item);
    });

    // 生成动态列:用索引做唯一ID,保留重复level的列
    this.rawData.forEach((item, idx) => {
      const columnId = `level_col_${idx}`;
      this.dynamicColumns.push({ id: columnId, label: item.level.toString() });
      this.displayedColumns.push(columnId);
    });

    // 构造表格数据源
    const tableData: TableData[] = [];
    questionGroups.forEach((items, question) => {
      const comments: { [key: string]: string } = {};
      items.forEach(item => {
        const targetIdx = this.rawData.findIndex(raw => 
          raw.Question === question && raw.low === item.low && raw.high === item.high
        );
        if (targetIdx !== -1) {
          const columnId = `level_col_${targetIdx}`;
          comments[columnId] = `${item.low} - ${item.high}`;
        }
      });
      tableData.push({ question, comments });
    });

    this.dataSource.data = tableData;
  }
}

2. 编写HTML模板

用*ngFor渲染动态列,同时处理双层表头:

<div class="mat-elevation-z8">
  <table mat-table [dataSource]="dataSource">
    <!-- 固定列:Question -->
    <ng-container matColumnDef="question">
      <th mat-header-cell *matHeaderCellDef>
        <div>Level</div>
        <div><strong>Question</strong></div>
      </th>
      <td mat-cell *matCellDef="let element"> {{element.question}} </td>
    </ng-container>

    <!-- 动态列:每个Level对应的Comment列 -->
    <ng-container *ngFor="let col of dynamicColumns" [matColumnDef]="col.id">
      <th mat-header-cell *matHeaderCellDef>
        <div>{{col.label}}</div>
        <div><strong>Comment</strong></div>
      </th>
      <td mat-cell *matCellDef="let element"> {{element.comments[col.id] || ''}} </td>
    </ng-container>

    <!-- 渲染表头和数据行 -->
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>
</div>

3. 样式优化(可选)

添加CSS让表头布局更美观:

.mat-header-cell div {
  text-align: center;
  line-height: 1.6;
}
.mat-cell {
  text-align: center;
}

关键说明
  • 用Map按问题分组,确保每个问题只生成一行数据
  • 动态列用索引拼接唯一ID,解决重复level列的标识冲突问题
  • 数据源中通过列ID映射对应区间文本,渲染时直接取值即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:57:40