Angular Mat-Table动态生成列并横向展示嵌套JSON数据求助
解决方案
问题根因
- 原实现错误在单个
<td>内嵌套多个<td>,违反HTML表格结构规范,浏览器自动修正DOM结构导致内容丢失 - 动态列生成逻辑错误:每组条件对应3个独立列,原逻辑仅生成1个列承载3个字段,不符合MatTable的列渲染规则
- 表头未做语义化处理,显示内容无法识别
修复后组件TS代码
import { Component, OnInit } from '@angular/core'; import { MatTableDataSource } from '@angular/material/table'; export class SamplePocComponent implements OnInit { lstRulesCheck: MatTableDataSource<any>; displayedColumns: string[] = ['SAMPLERULENAME']; payload: any[] = [ {"SAMPLERULEID": 69,"SAMPLERULENAME": "Sample1","SAMPLERULECONDITIONS": [{"SAMPLERULECONDITIONID": 148,"SAMPLERULEID": 69,"SAMPLERULENAME": "Sample1","CONDITIONFIELDID": 1,"DISPLAYNAME": "Country","OPERATOR": "=","COUNT": 10},{"SAMPLERULECONDITIONID": 149,"SAMPLERULEID": 69,"SAMPLERULENAME": "Sample1","CONDITIONFIELDID": 2,"DISPLAYNAME": "State","OPERATOR": "=","COUNT": 11},{"SAMPLERULECONDITIONID": 150,"SAMPLERULEID": 69,"SAMPLERULENAME": "Sample1","CONDITIONFIELDID": 3,"DISPLAYNAME": "City","OPERATOR": "="},{"SAMPLERULECONDITIONID": 151,"SAMPLERULEID": 69,"SAMPLERULENAME": "Sample1","CONDITIONFIELDID": 4,"DISPLAYNAME": "Town","OPERATOR": "IS NULL"}]},{"SAMPLERULEID": 80,"SAMPLERULENAME": "Sample123","SAMPLERULECONDITIONS": [{"SAMPLERULECONDITIONID": 208,"SAMPLERULEID": 80,"SAMPLERULENAME": "Sample123","CONDITIONFIELDID": 92,"DISPLAYNAME": "Date","OPERATOR": "IS NOT NULL","COUNT": 12}]},{"SAMPLERULEID": 74,"SAMPLERULENAME": "Sample2","SAMPLERULECONDITIONS": [{"SAMPLERULECONDITIONID": 153,"SAMPLERULEID": 74,"SAMPLERULENAME": "Sample2","CONDITIONFIELDID": 89,"DISPLAYNAME": "Primary","OPERATOR": "IS NOT NULL","COUNT": 5},{"SAMPLERULECONDITIONID": 156,"SAMPLERULEID": 74,"SAMPLERULENAME": "Sample2","CONDITIONFIELDID": 90,"DISPLAYNAME": "Secondary","OPERATOR": ">","COUNT": 9},{"SAMPLERULECONDITIONID": 157,"SAMPLERULEID": 74,"SAMPLERULENAME": "Sample2","CONDITIONFIELDID": 89,"DISPLAYNAME": "Third","OPERATOR": "IS NULL","COUNT": 99}]} ]; maxConditionCount: number = 0; constructor() {} ngOnInit() { this.getSampleRules(); } getSampleRules() { // 计算最大条件数 this.payload.forEach(element => { const conditionLen = element.SAMPLERULECONDITIONS?.length || 0; if (conditionLen > this.maxConditionCount) { this.maxConditionCount = conditionLen; } }); // 生成动态列:每个条件对应3列:字段名/操作符/数量 for (let i = 1; i <= this.maxConditionCount; i++) { this.displayedColumns.push(`condition${i}_name`); this.displayedColumns.push(`condition${i}_operator`); this.displayedColumns.push(`condition${i}_count`); } this.lstRulesCheck = new MatTableDataSource(this.payload); } // 获取单元格值 getCellValue(col: string, element: any): any { if (col === 'SAMPLERULENAME') return element.SAMPLERULENAME; // 拆分列名:condition1_name 拆出索引0,属性name const [conditionPrefix, field] = col.split('_'); const conditionIndex = parseInt(conditionPrefix.replace('condition', '')) - 1; const condition = element.SAMPLERULECONDITIONS?.[conditionIndex]; if (!condition) return ''; // 映射字段 const fieldMap = { name: 'DISPLAYNAME', operator: 'OPERATOR', count: 'COUNT' }; return condition[fieldMap[field]] ?? ''; } // 获取表头显示名称 getHeaderText(col: string): string { if (col === 'SAMPLERULENAME') return '规则名称'; const [conditionPrefix, field] = col.split('_'); const conditionNum = conditionPrefix.replace('condition', ''); const fieldTextMap = { name: '字段', operator: '操作符', count: '数量' }; return `条件${conditionNum}${fieldTextMap[field]}`; } }
修复后模板代码
<table mat-table [dataSource]="lstRulesCheck" class="mat-elevation-z8 w-full"> <ng-container *ngFor="let col of displayedColumns" [matColumnDef]="col"> <th mat-header-cell *matHeaderCellDef> {{getHeaderText(col)}} </th> <td mat-cell *matCellDef="let element" style="word-break: break-all; padding: 8px 16px;"> {{getCellValue(col, element)}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
实现效果
- 自动按所有规则的最大条件数生成对应列,无多余空列
- 条件数不足的规则对应单元格自动留空
- 所有字段正常渲染,结构符合MatTable规范
- 表头语义化显示,用户可直接识别列含义
内容的提问来源于stack exchange,提问作者Karthik Myakala
相关产品推荐
相关产品推荐

