我不得不构建许多使用 Angular Material 的MatTable 的表格组件,从长远来看,我决定通过构建一个动态且可重用的基表来节省自己一些时间。在讨论如何向其中添加特定功能之前,我已经添加了更多关于如何启动和运行最小动态可重用表的上下文/思考过程。
构建动态和可重用表的建议
我做的第一件事(在项目中添加 Angular 材质之后)是确定我希望消费者如何使用我的表格。我决定任何表格级别的行为(启用/禁用分页)都将由表格组件中的@Input 控制。然而,随着我进一步开发它,我意识到我需要的大部分新功能实际上应该按列进行控制。此答案的其余部分侧重于每列配置。
TableColumnConfig 接口 - 添加新功能
我首先为配置对象定义了一个接口(就像 OP 对 TableColumns 所做的那样,除了我的称为 TableColumnConfig。动态和可重用功能所需的最低限度是用于访问数据的两个字符串在每一行中显示列名(我使用key 和displayName)。
如果我们想为组件的消费者添加传递自定义单元格模板的功能,我首先要向TableColumnConfig 接口添加一个属性,如下所示:
import { TemplateRef } from '@angular/core';
export interface TableColumnConfig {
displayName: string;
key: string;
customCellTemplate?: TemplateRef<any>; // custom cell template!
}
my-table-component.ts
我相信我从用于生成表格组件的 Angular Material 示意图开始,但我不喜欢像这个示例这样的最低限度的样板数量(稍后添加分页和排序很容易)。
您不需要在 table-component.ts 中执行任何特殊操作来自定义自定义单元格模板功能(请注意,我们期望来自消费组件的TableColumnConfig[]),但为了完整性,请显示下面的代码。大多数时候,当我需要添加每列功能时,我什至不必弄乱这个文件。
import { Component, OnInit, Input } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import { TableColumnConfig } from './table-column-config';
@Component({
selector: 'app-my-table',
templateUrl: './my-table.component.html',
styleUrls: ['./my-table.component.css']
})
export class MyTableComponent implements OnInit {
@Input() data: any[];
@Input() columnConfigs: TableColumnConfig[];
dataSource: MatTableDataSource<any>;
// need a string array for *matHeaderRowDef and *matRowDef
displayedColumns: string[];
ngOnInit() {
this.displayedColumns = this.columnConfigs.map(config => config.key);
this.dataSource = new MatTableDataSource(this.data);
}
}
my-table-component.html
OP 在他的回答中显示的类似方法。由于我将customCellTemplate 作为属性添加到TableColumnConfig,因此访问它看起来更简洁。另外请注意,对于此演示,我决定仅将列数据公开给 customCellTemplates,但如果需要,您可以通过将 $implicit: row[col.key] 更改为 $implicit: row 轻松返回整行
<div class="mat-elevation-z8">
<mat-table class="full-width-table" [dataSource]="dataSource">
<!-- NgFor Columns -->
<ng-container *ngFor="let col of columnConfigs" matColumnDef="{{ col.key }}">
<mat-header-cell *matHeaderCellDef> {{ col.displayName }}
</mat-header-cell>
<mat-cell *matCellDef="let row">
<!-- handle custom cell templates -->
<div *ngIf="!col.customCellTemplate; else customCellTemplate">
{{ row[col.key] }}
</div>
<ng-template #customCellTemplate>
<!-- for now, only exposing row[col.key] instead of entire row -->
<ng-template [ngTemplateOutlet]="col.customCellTemplate"
[ngTemplateOutletContext]="{ $implicit: row[col.key] }">
</ng-template>
</ng-template>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>
</div>
示例:消费组件
我们希望在列中设置样式文本的示例用例
app-component.html
对于这个最简单的示例,表格只有两个输入。我喜欢在文件底部而不是在表格标签本身内部为 customCellTemplates 定义<ng-template>s,以提高 imo 的可读性。
<app-my-table [data]="tableData" [columnConfigs]="columnConfigs">
</app-my-table>
<!-- Custom cell template for color column -->
<!-- name the $implicit variable 'let-whateverIwant' -->
<ng-template #customCell let-colorData>
<span [ngStyle]="{'color': colorData}">{{colorData}}</span>
</ng-template>
app-component.ts
export class AppComponent implements OnInit {
@ViewChild("customCell", { static: true })
customCell: TemplateRef<any>;
columnConfigs: TableColumnConfig[];
tableData = [
{ id: 1, name: "Chris", color: "#FF9900" },
{ id: 2, name: "Akash", color: "blue" }
];
// we can't reference our {static:true} TemplateRef until ngOnInit
ngOnInit() {
this.columnConfigs = [
{ key: "id", displayName: "ID" },
{ key: "name", displayName: "Name" },
{
key: "color",
displayName: "Favorite Color",
customCellTemplate: this.customCell
}
];
}
}
查看我的StackBlitz demo 了解更多代码 cmets。