5

我想知道是否可以将 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>

有可能吗,以前有人做过吗?

4

2 回答 2

7

我创建了一个自定义TableComponent,它使用@Directivewithng-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);
    }
}

@ComponentHTML 只是添加mat-header-cellmat-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. 以它为起点,我敢肯定,您将能够构建适合您需求的定制解决方案。

于 2018-03-18T11:10:25.230 回答
0

非常感谢您的解决方案本杰明

你能想出一个更好(更像 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>

TableColmnHeader 指令:

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];
  }
}

表格组件:

...
ngAfterContentInit() {
        this.columnHeaders = ArrayHelper.toMap(
          this.columnHeaderDirectives.toArray(),
          (val: TableColumnHeaderDirective) => val.column
        );
      }
...

表.html

<mat-header-cell *matHeaderCellDef>
    {{columnHeaders.get(column)?.header}}
</mat-header-cell>
于 2018-07-06T13:21:41.613 回答