如何使用Angular Mat-Table按列值透视展示数据?
问题描述
我有如下结构的数据源:
[{ "testDisplayName": "Test_Name_1", "data": { "metrics": [ { "metricValue": -0.18, "metricKey": "metricKey_1" }, { "metricValue": 3.9, "metricKey": "metricKey_2" }, ] }, "url": "some_url", "revision": "rev1", "dId": "dId_1", "release": "release_1", "buildId": "build_1" }, { "testDisplayName": "Test_Name_1", "data": { "metrics": [ { "metricValue": -0.20, "metricKey": "metricKey_3" }, { "metricValue": 3.8, "metricKey": "metricKey_4" }, ] }, "url": "url_2", "revision": "rev2", "dId": "dId_2", "release": "release_2", "buildId": "build_2" }]
我希望用Angular Mat-Table将上述数据展示为如下表格形式:
build_1 release_1 build_2 release_2 => 这些是来自数据的动态值 Metric Key Metric value Metric Value => 静态列名 metricKey_1 -0.18 3.9 metricKey_2 -0.20 3.8
表格数据会根据testDisplayName进行过滤,不同的testDisplayName对应不同的metricKey和metricValue,例如当前过滤条件为Test_Name_1。
我的疑问是:这种需求能否通过Angular Mat-Table实现?因为我了解到Mat-Table不允许displayColumn中存在重复列名,也无法在单个单元格中展示两个数据值(如build_1 release_1),恳请提供帮助或指引,感谢!
解决方案
完全可以实现,核心是先转换数据源结构,再配合Mat-Table的动态列和多行表头功能处理:
1. 转换数据源
将原始数据转换成以metricKey为行标识、各构建版本的metricValue为列值的结构:
// 先过滤出目标testDisplayName的数据 const filteredData = originalData.filter(item => item.testDisplayName === 'Test_Name_1'); // 提取所有唯一的metricKey(合并所有条目里的metrics) const allMetricKeys = Array.from(new Set(filteredData.flatMap(item => item.data.metrics.map(m => m.metricKey)))); // 构造表格最终数据源 this.tableDataSource = allMetricKeys.map(key => { const row: any = { metricKey: key }; filteredData.forEach((item, index) => { // 匹配当前构建下对应metricKey的值,无匹配则设为null const metric = item.data.metrics.find(m => m.metricKey === key); row[`build_col_${index}`] = metric ? metric.metricValue : null; }); return row; });
2. 生成动态列配置
为每个构建版本生成唯一的列标识,同时记录表头显示文本:
// 初始化固定列+动态列集合 this.displayedColumns = ['metricKey']; this.buildColumnConfigs = filteredData.map((item, index) => { const columnKey = `build_col_${index}`; this.displayedColumns.push(columnKey); return { key: columnKey, headerText: `${item.buildId} ${item.release}` // 合并buildId和release作为表头 }; });
3. 模板中实现表格
通过多行表头解决分组展示需求,用动态列处理不同构建版本的数据:
<table mat-table [dataSource]="tableDataSource" class="mat-elevation-z8"> <!-- 第一行表头:构建版本信息 --> <ng-container matHeaderRowDef="buildHeaderRow"> <tr mat-header-row> <th mat-header-cell></th> <th mat-header-cell *ngFor="let col of buildColumnConfigs"> {{ col.headerText }} </th> </tr> </ng-container> <!-- 第二行表头:静态列名 --> <ng-container matHeaderRowDef="staticHeaderRow"> <tr mat-header-row> <th mat-header-cell>Metric Key</th> <th mat-header-cell *ngFor="let col of buildColumnConfigs">Metric Value</th> </tr> </ng-container> <!-- Metric Key固定列 --> <ng-container matColumnDef="metricKey"> <td mat-cell *matCellDef="let element">{{ element.metricKey }}</td> </ng-container> <!-- 动态构建列 --> <ng-container *ngFor="let col of buildColumnConfigs" [matColumnDef]="col.key"> <td mat-cell *matCellDef="let element">{{ element[col.key] }}</td> </ng-container> <!-- 表格数据行 --> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> <!-- 渲染两行表头 --> <tr mat-header-row *matHeaderRowDef="['buildHeaderRow', 'staticHeaderRow']; sticky: true"></tr> </table>
关键说明
- 重复列名问题:通过生成唯一的列标识(如
build_col_0、build_col_1)解决,Mat-Table仅要求matColumnDef的值唯一,表头显示文本可重复。 - 单元格多值展示:直接在模板中拼接
buildId和release作为表头文本,无需特殊处理。 - 适配不同testDisplayName:切换过滤条件时,重新执行数据源转换和列配置生成逻辑即可更新表格。
内容的提问来源于stack exchange,提问作者Kishore Khan
相关产品推荐
相关产品推荐

