
本文介绍如何将包含多个对象的数组,以每项字段名与对应值成对垂直排列的方式渲染为 html 表格,避免传统横向表格结构,满足审计日志等场景中清晰展示单条记录全字段的需求。
本文介绍如何将包含多个对象的数组,以每项字段名与对应值成对垂直排列的方式渲染为 html 表格,避免传统横向表格结构,满足审计日志等场景中清晰展示单条记录全字段的需求。
在 Angular 应用中,当需要展示类似操作历史(如 changeLogEntries)这类结构化数据时,常见需求并非横向宽表(一行一记录、一列一字段),而是纵向展开式展示:即每个字段独占一行,左侧显示字段名(如 registrarSurname),右侧显示其值(如 "Jan"),形成清晰易读的键值对列表。
原始实现中,开发者使用了 <table mat-table [dataSource]="[entry]"> 并为每个字段单独定义 <ng-container matColumnDef="...">,导致模板冗长、难以维护,且实际渲染为标准横向表格(多列并排),不符合“字段名+值垂直堆叠”的设计目标。
✅ 正确解法是放弃 Material Table 的列驱动模式,改用语义化循环直接遍历字段名数组,动态生成行级结构:
<div *ngFor="let entry of history">
<table class="history-detail-table" aria-label="History entry details">
<tr *ngFor="let key of displayedColumns">
<th scope="row" class="field-name">{{ key | titlecase }}</th>
<td class="field-value">{{ entry[key] || '-' }}</td>
</tr>
</table>
</div>? 关键要点说明:
- *ngFor="let key of displayedColumns" 遍历预定义字段名数组(如 ['lp', 'objectId', 'registrarSurname', ...']),确保顺序可控、可配置;
- 每次迭代生成一个 <tr>,内含 <th>(字段名)和 <td>(字段值),天然实现“名称-值”垂直对齐;
- 使用 entry[key] 动态取值,无需为每个字段硬编码模板,大幅提升可维护性;
- 添加 || '-' 提供空值兜底,避免 undefined 显示;
- 推荐配合 CSS 控制样式(如固定 th 宽度、右对齐、加粗等),增强可读性:
.history-detail-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 16px;
}
.history-detail-table th,
.history-detail-table td {
padding: 8px 12px;
border-bottom: 1px solid #eee;
}
.field-name {
text-align: right;
font-weight: 500;
color: #555;
min-width: 140px;
}
.field-value {
text-align: left;
font-family: var(--font-mono, monospace);
}⚠️ 注意事项:
- 确保 displayedColumns 中的字段名全部存在于 entry 对象中,否则会显示 undefined(建议结合 ?. 或管道做安全访问);
- 若字段值含日期、布尔值等需格式化,可在插值中调用管道,例如 {{ entry.entryDate | date:'short' }};
- 如需支持国际化字段名(如 registrarSurname → “姓氏”),可结合 TranslatePipe:{{ key | translate }};
- 此方案不依赖 MatTableDataSource,因此无需引入 MatTableModule 的完整功能,轻量高效。
通过该方式,每条历史记录将被渲染为一张紧凑、语义清晰的垂直表格,完美匹配“No. 1 → Surname → Jan → Firstname → John…”的展示逻辑,显著提升信息扫描效率与用户体验。

















