Angular Material Table 没有模型的动态列

Angular Material Table Dynamic Columns without model

我需要使用没有模型的angular material table,因为我不知道服务会带来什么。

所以我在这样的组件中动态初始化我的 MatTableDataSourcedisplayedColumns :

Table分量:

ngOnInit() {

this.vzfPuanTablo = [] //TABLE DATASOURCE

//GET SOMETHING FROM SERVICE 
this.listecidenKisi = this.listeciServis.listecidenKisi;
this.listecidenVazife = this.listeciServis.listecidenVazife;

//FILL TABLE DATASOURCE 
var obj = {};
for (let i in this.listecidenKisi ){
    for( let v of this.listecidenVazife[i].vazifeSonuclar){
        obj[v.name] = v.value;
    }
    this.vzfPuanTablo.push(obj);
    obj={};
}

//CREATE DISPLAYED COLUMNS DYNAMICALLY
this.displayedColumns = [];
for( let v in this.vzfPuanTablo[0]){
    this.displayedColumns.push(v);
}

//INITIALIZE MatTableDataSource
this.dataSource = new MatTableDataSource(this.vzfPuanTablo);
}

代码最重要的部分在这里:

for( let v in this.vzfPuanTablo[0]) {
   this.displayedColumns.push(v);
}

我在这里动态创建displayedColumns,这意味着;即使我不知道服务会带来什么,我也可以在 table.

中展示

例如displayedColumns可以这样:

但这不是问题,因为我可以处理。


但是当我想在HTML中显示时,我无法正常显示,因为 matCellDef 东西:

TableHTML :

    <mat-table #table [dataSource]="dataSource" class="mat-elevation-z8">

        <ng-container *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
            <mat-header-cell *matHeaderCellDef>{{disCol}}</mat-header-cell>
            <mat-cell *matCellDef="let element "> {{element.disCol}}
            </mat-cell>
        </ng-container>

        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>

我的问题在这里:

<mat-cell *matCellDef="let element "> {{element.disCol}} < / mat-cell>

事实上,我想在单元格中显示element."disCol's value",但我不知道该怎么做。

否则,除了这个element."disCol's value"东西,其他都还好。


当我使用 {{element.disCol}} 显示 value of element that has disCols's value 时,所有单元格都是空的:

仅使用 {{element}} 的其他示例:


也可以看到:

  1. Table 数据源正在动态变化。这意味着我不能轻易使用 {{element.ColumnName}},因为我什至不知道它是什么。

    • 第一个示例的显示列 = ['Vazife', 'AdSoyad', 'Kirmizi', 'Mavi', 'Yesil', 'Sari'];
    • 第二个例子的 displayedColumns = ['Muhasebe', 'Ders', 'Egitim', 'Harici'];
  2. matHeaderCellDef 是正确的,因为它是直接使用 {{disCol}}。

但我需要读取disCol的值,并在单元格中显示element.(disCol's value)

我该怎么做?

我找到了解决办法:) 这非常非常容易,但我一开始看不到 :) 就这样:

        <mat-cell *matCellDef="let element "> {{element[disCol]}}
        </mat-cell>

我必须只在 HTML 中使用 {{element[disCol]}}

现在,一切正常:)

有关基于@mevaka 的完整工作示例

其中 jobDetails$ 是项目数组。

columns$ 等同于 Object.keys(jobDetails$[0]) 所以只是一个 string[]

  <table mat-table [dataSource]="jobDetails$ | async">

    <ng-container *ngFor="let disCol of (columns$ | async); let colIndex = index" matColumnDef="{{disCol}}">
      <th mat-header-cell *matHeaderCellDef>{{disCol}}</th>
      <td mat-cell *matCellDef="let element">{{element[disCol]}}</td>
    </ng-container>


    <tr mat-header-row *matHeaderRowDef="(columns$ | async)"></tr>
    <tr mat-row *matRowDef="let row; columns: (columns$ | async)"></tr>
  </table>

我已尽力将动态 table 压缩到最低限度。此示例将显示给定具有任何键的平面对象数组的任何列。请注意第一个对象如何有一个额外的“foo”属性 导致创建整个列。 DATA 常量可以是您从服务中获得的一些数据。此外,如果您知道一些常见的 属性 名称,您可以将“列 ID -> 标签”映射添加到其中,您将获得 JSON。查看 stachblitz here.

import {Component, ViewChild, OnInit} from '@angular/core';

const DATA: any[] = [
  {position: 1, name: 'sdd', weight: 1.0079, symbol: 'H', foo: 'bar'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}
];

@Component({
  selector: 'dynamic-table-example',
  styleUrls: ['dynamic-table-example.css'],
  templateUrl: 'dynamic-table-example.html',
})
export class DynamicTableExample implements OnInit {

  columns:Array<any>
  displayedColumns:Array<any>
  dataSource:any
  
  ngOnInit() {
    // Get list of columns by gathering unique keys of objects found in DATA.
    const columns = DATA
      .reduce((columns, row) => {
        return [...columns, ...Object.keys(row)]
      }, [])
      .reduce((columns, column) => {
        return columns.includes(column)
          ? columns
          : [...columns, column]
      }, [])
    // Describe the columns for <mat-table>.
    this.columns = columns.map(column => {
      return { 
        columnDef: column,
        header: column,
        cell: (element: any) => `${element[column] ? element[column] : ``}`     
      }
    })
    this.displayedColumns = this.columns.map(c => c.columnDef);
    // Set the dataSource for <mat-table>.
    this.dataSource = DATA
  }
 
}
<mat-table #table [dataSource]="dataSource">
  <ng-container *ngFor="let column of columns" [cdkColumnDef]="column.columnDef">
    <mat-header-cell *cdkHeaderCellDef>{{ column.header }}</mat-header-cell>
    <mat-cell *cdkCellDef="let row">{{ column.cell(row) }}</mat-cell>
  </ng-container>
  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>