如何使用带有ngFor的mat-table设置动态dataSource?

时间:2018-04-20 06:32:04

标签: angular angular-material

我正在使用Angular Material制作仪表板。在那个仪表板上,我想为每个服务器显示一张卡(到目前为止一直很好),并且在该卡中我想要在该特定服务器上显示一个与客户相关的表。这就是我被困的地方。

当使用下面的代码时,我得到以下错误(对于每个表):

ERROR Error: Could not find column with id "name".

我的相关代码:

<mat-card class="card" *ngFor="let listItem of serverList; let i = index">
  <mat-card-header>
    <div mat-card-avatar class="card-header-image"></div>
    <mat-card-title>{{listItem.name}} - {{ listItem.datasource }}</mat-card-title>
    <mat-card-subtitle>{{listItem.url}} - {{listItem.status}}</mat-card-subtitle>
  </mat-card-header>
  <mat-card-content>
    <div class="table-container mat-elevation-z8">
      <mat-table #table [dataSource]="listItem.datasource" matSort>
        <ng-container matColumnDef="klant">
          <mat-header-cell *matHeaderCellDef mat-sort-header> Klant </mat-header-cell>
          <mat-cell *matCellDef="let element"> {{ element.name }} </mat-cell>
        </ng-container>
        <ng-container matColumnDef="status">
          <mat-header-cell *matHeaderCellDef mat-sort-header> Status </mat-header-cell>
          <mat-cell *matCellDef="let element"> {{ element.status }} </mat-cell>
        </ng-container>
        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
      </mat-table>
    </div>
  </mat-card-content>
</mat-card>

this.fbService.getServerList().subscribe( data => {
  this.serverList = data;
});

注意:我使用Firestore存储服务器和客户。

重要的是我的问题是如何动态设置[dataSource]:

<mat-table #table [dataSource]="listItem.datasource" matSort>

3 个答案:

答案 0 :(得分:0)

我认为dataSource必须是MatTableDataSource类型

您可以像这样实例化一个dataSource:

this.dataSource = new MatTableDataSource(this.myList);

在您从服务中收到这些值后尝试并映射这些值:

&#13;
&#13;
this.fbService.getServerList().subscribe(data => {
      this.serverList = data.map(el =>
        el.dataSource = new MatTableDataSource(el.dataSource);
      });
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我不知道这是否相似,但是我使用Mat Mat Accordion面板对项目进行分组,并且在展开时显示子项目的mat表。

这很容易,因为我使用的类别数组包含一系列子产品。

*ngFor="let cat of categories let i = index;"

在桌子上...

table mat-table [dataSource]="cat.products"

以这种方式进行操作意味着手风琴没有在单击时进行http调用,并且可以按您期望的那样工作。美中不足的唯一苍蝇是更新。

将表数据源设置为迭代的子数组意味着未为其分配MatTableDataSource,并且您无法访问其方法更新对象。

不要害怕Viewchildren来救援

  @ViewChildren(MatTable)
  tables: QueryList<MatTable<IProduct>>;

...这使我可以访问视图中的所有表。

这应该允许您进行表更新/删除和操作。例如,如果您在表中添加了新行,请调用renderRows方法以使它们出现在表中。

  refreshTables(): void {
    this.tables.forEach(tbl => tbl.renderRows());
  }

我相信您有更好的方法来做到这一点。我希望它能为您提供线索。

答案 2 :(得分:0)

我在项目中遇到了同样的问题,我通过做一个简单的功能解决了这个问题。

<mat-grid-tile *ngFor="let card of cards | async" [colspan]="card.cols" [rowspan]="card.rows">
<table mat-table [dataSource]="getDataSource(card.title)">

并在打字稿文件中

tableData1: MatTableDataSource<any>;
tableData2: MatTableDataSource<any>;


cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
    map(({ matches }) => {
      if (matches) {
        return [
          { title: 'Title 1', cols: 2, rows: 1 },
          { title: 'Title 2', cols: 2, rows: 1 },
        ];
      }

      return [
        { title: 'Title 1', cols: 1, rows: 1 },
        { title: 'Title 2', cols: 1, rows: 1 },
      ];
    })
  );

ngOnInit(): void {
 this.auth.user$.subscribe(user => {
      this.user = user;
      this.afs.collection('post', ref => ref.where('dateTime','>=', this.todayDate).where('createdBy', '==', this.user.uid)).valueChanges().subscribe(data => {
        this.tableData1 = new MatTableDataSource(data);
      });
this.afs.collection('post', ref => ref.where('dateTime','<=', this.todayDate).where('createdBy', '==', this.user.uid)).valueChanges().subscribe(data => {
        this.tableData2 = new MatTableDataSource(data);
      });
    });
    }

函数如下:

getDataSource(title) {
if(title==='Title 1') {
  return this.tableData1;
}
else return this.tableData2;
}

这个简单的功能帮了我大忙!