我想知道是否可以将mat表行放在与表组件不同的另一个组件中,这是一个示例:
<mat-table #table [dataSource]="dataSource" class="table" matSort>
<user-table-row> </user-table-row>
<ng-container matColumnDef="profile">
<mat-header-cell *matHeaderCellDef mat-sort-header class="header-cell"> Profile Type </mat-header-cell>
<mat-cell *matCellDef="let user" class="cell"> {{user.profile.type}} </mat-cell>
</ng-container>
<ng-container matColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header class="header-cell"> Status </mat-header-cell>
<mat-cell *matCellDef="let user" class="cell"> {{user.profile.status}} </mat-cell>
</ng-container>
<!-- Header and Row Declarations -->
<mat-header-row *matHeaderRowDef="['createdAt', 'email', 'profile', 'status', 'isApproved', 'actions']" class="header-row"></mat-header-row>
<mat-row *matRowDef="let row; columns: ['createdAt', 'email', 'profile', 'status', 'isApproved', 'actions']" class="row"></mat-row>
</mat-table>
我如何制作这样的东西:
<mat-table #table [dataSource]="dataSource" class="table" matSort>
<user-table-row> </user-table-row>
</mat-table>
有可能,之前有人这么做过吗?
答案 0 :(得分:3)
我已经创建了一个自定义TableComponent
,它使用@Directive
和ng-template
来定义列。这非常灵活,可以抽象出所有重要的东西。因此,您可以在整个应用程序中获得通用的表格设计。您只需在此组件内定义一切。
我只会包含相关部分。
@Directive
用于获取ng-template
与材料表列名称之间的映射。
@Directive({ selector: 'ng-template[rowColumn]' })
export class TableRowColumnDirective {
@Input() rowColumn: string;
constructor(public templateRef : TemplateRef<any>) { }
}
@Component
提取所有ng-templates
并构建Map
以按名称访问ng-templates
。
@Component({
selector: 'my-table',
templateUrl: './table.component.html'
})
export class TableComponent<T> {
@ContentChildren(TableRowColumnDirective) rowColumnDirectives: QueryList<TableRowColumnDirective>;
displayedColumns: ['foo', 'bar'];
// I use a Map here only, because it's much easier to access the
// provided ng-templates within table.component.html
rowColumnTemplates: Map<string, TableRowColumnDirective>;
ngAfterContentInit() {
// ArrayUtils.toMap is just a little helper function, which
// converts an array to a Map. In this case the value of
// `rowColumn` will become the key of the map
this.rowColumnTemplates = ArrayUtils.toMap(this.rowColumnDirectives.toArray(), val => val.rowColumn);
}
}
@Component
的HTML只是使用mat-header-cell
循环添加mat-cell
和*ngFor
。然后,将使用提供的ng-template
s
<mat-table ...>
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
<mat-header-cell *matHeaderCellDef>
HEADER CONTENT
</mat-header-cell>
<mat-cell *matCellDef="let row">
<ng-container [ngTemplateOutlet]="rowColumnTemplates.get(column).templateRef" [ngTemplateOutletContext]="{$implicit: row}"></ng-container>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
然后可以像这样使用该表:
<my-table>
<!-- rowColumn matches the displayedColumns array -->
<ng-template rowColumn="foo" let-row>{{row.profile.type}}</ng-template>
<ng-template rowColumn="bar" let-customRowName>{{row.profile.status}}</ng-template>
</my-table>
现在,您可以为标题列添加另一个@Directive
。在我提供的示例中,标题始终为HEADER CONTENT
。它基本上只是TableRowColumnDirective
的副本。
我知道这并不是完全您正在寻找的内容,但我想您可以看到如何将自定义行注入mat-table
。以此为出发点,我确信,您将能够构建满足您需求的自定义解决方案。
答案 1 :(得分:0)
非常感谢您的解决方案Benjamin
您能想到一个更好的(更像Angular的)列标题解决方案吗?
这是我想出的:
<my-table>
<!-- rowColumn matches the displayedColumns array -->
<ng-template rowColumn="foo" appColumnHeader="foo##MyCustomFooName" let-row>{{row.profile.type}}</ng-template>
<ng-template rowColumn="bar" let-customRowName>{{row.profile.status}}</ng-template>
</my-table>
TableColmnHeaderDirective:
import { Directive, Input, OnInit } from '@angular/core';
@Directive({
selector: 'ng-template[appColumnHeader]',
})
export class TableColumnHeaderDirective implements OnInit {
@Input() appColumnHeader: string;
public column: string;
public header: string;
constructor() {}
ngOnInit() {
const splitted = this.appColumnHeader.split('##');
this.column = splitted[0];
this.header = splitted[1];
}
}
TableComponen:
...
ngAfterContentInit() {
this.columnHeaders = ArrayHelper.toMap(
this.columnHeaderDirectives.toArray(),
(val: TableColumnHeaderDirective) => val.column
);
}
...
table.html
<mat-header-cell *matHeaderCellDef>
{{columnHeaders.get(column)?.header}}
</mat-header-cell>