Angular12自定义表格组件如何从ts文件设置td动态内容
问题原因
Angular的模板语法(包括{{}}插值表达式、routerLink等内置指令)只会在编译阶段被解析处理,你通过innerHTML传入的内容属于运行时插入的纯字符串,不会经过Angular编译器的处理,因此只会作为普通文本/静态HTML渲染,既无法解析插值语法拿到变量值,也无法激活路由、事件绑定等Angular能力。
推荐解决方案:使用ngTemplateOutlet实现自定义内容插槽
这是Angular生态里封装动态内容组件的标准方案,实现成本低、兼容性好,支持所有原生Angular模板能力:
步骤1:改造自定义表格组件
首先修改ColumnItem类型定义,新增模板引用属性:
// table.component.ts import { TemplateRef } from '@angular/core'; export interface ColumnItem { name: string; sortOrder: 'ascend'|'descend'|null; sortDirections: ('ascend'|'descend'|null)[]; columnKey: string; // 新增属性,接收外部传入的自定义单元格模板 tdTemplate?: TemplateRef<{$implicit: any}>; }
接着修改表格组件模板,使用ngTemplateOutlet渲染自定义内容:
<!-- table.component.html --> <thead> <tr> <th *ngFor="let column of listOfColumns"> {{ column.name }} </th> </tr> </thead> <tbody> <tr *ngFor="let data of sourceData"> <td *ngFor="let column of listOfColumns"> <!-- 传入了自定义模板就用模板,否则默认渲染对应字段的值 --> <ng-container *ngIf="column.tdTemplate; else defaultCell"> <ng-container *ngTemplateOutlet="column.tdTemplate; context: {$implicit: data}"></ng-container> </ng-container> <ng-template #defaultCell>{{ data[column.columnKey] }}</ng-template> </td> </tr> </tbody>
步骤2:父组件传入自定义模板
在使用表格组件的父组件中,先定义各列的单元格模板,再把模板传入列配置即可:
<!-- 父组件模板 --> <!-- 先定义自定义单元格模板,let-data接收当前行数据 --> <ng-template #nameCellTpl let-data> <a routerLink="/employeeInfo/{{data.Pid}}"> {{ data.Name }} </a> </ng-template> <ng-template #pidCellTpl let-data> {{ data.Pid }} </ng-template> <!-- 引用自定义表格组件 --> <app-custom-table [listOfColumns]="columnConfig" [sourceData]="tableData" ></app-custom-table>
// 父组件ts import { ViewChild, TemplateRef, AfterViewInit } from '@angular/core'; import { ColumnItem } from './table.component'; export class ParentComponent implements AfterViewInit { // 获取模板引用 @ViewChild('nameCellTpl') nameCellTpl!: TemplateRef<any>; @ViewChild('pidCellTpl') pidCellTpl!: TemplateRef<any>; columnConfig: ColumnItem[] = []; tableData = []; // 你的表格数据源 ngAfterViewInit() { // 模板初始化完成后再组装列配置 this.columnConfig = [ { name: 'EmployeeName', sortOrder: null, sortDirections: ['ascend', 'descend', null], columnKey: 'Name', tdTemplate: this.nameCellTpl }, { name: 'EmployeeId', sortOrder: null, sortDirections: ['ascend', 'descend', null], columnKey: 'pId', tdTemplate: this.pidCellTpl } ]; } }
轻量场景替代方案
如果你的自定义单元格只有纯文本内容、不需要用到指令/事件绑定,也可以把tdContent定义为函数类型,直接调用函数获取渲染值:
// ColumnItem定义 export interface ColumnItem { // 其他属性不变 tdContent?: (data: any) => string; } // 列配置 listOfColumns: ColumnItem[] = [ { name: 'EmployeeId', columnKey: 'pId', tdContent: (data) => `ID:${data.Pid}` } ]
<!-- 表格模板td部分 --> <td *ngFor="let column of listOfColumns"> {{ column.tdContent ? column.tdContent(data) : data[column.columnKey] }} </td>
不推荐你继续使用innerHTML的方案,除了无法支持Angular模板能力外,还存在XSS安全风险,手动解析插值表达式和指令的成本也非常高。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

