0

I have created an HTML table which will generate infinite columns based on the number of rows in the input data. I've tried to use this SO post as an example, but I'm struggling to convert my HTML to Angular Material design. Any suggestions?

StackBlitz demo

Since Angular material tables are column-based (and I couldn't find a way to iterate over the rows within them) I got stuck pretty quickly.

I couldn't get angular material tables working in the StackBlitz, so here is a copy paste of my code:

<table mat-table [dataSource]="newLicenseDS">

    <ng-container *ngFor="let disCol of newLicCol; let idx = index" matColumnDef="{{disCol}}">
        <th mat-header-cell *matHeaderCellDef>{{disCol}}</th>
        <ng-container *ngIf="idx==0">
           <td mat-cell *matCellDef="let e">{{e[0]|json}}</td>
        </ng-container>
        <ng-container *ngIf="idx==1">
           <td mat-cell *matCellDef="let e">{{e[1]|json}}</td>
        </ng-container>
        <ng-container *ngIf="idx==2">
           <td mat-cell *matCellDef="let e[2]">{{e|json}}</td>
        </ng-container>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="newLicCol"></tr>
    <tr mat-row *matRowDef="let row; columns: newLicCol"></tr>
</table>
Rilcon42
  • 7,248
  • 11
  • 51
  • 127
  • Why? Is this there any real reason? Performance will bite you. – Vova Bilyachat Aug 26 '19 at 00:36
  • It doesn't have to be infinite, but I can't tell how many columns there will be in advance, it's likely far less than a hundred columns, but I can't guarantee that, which is why I'm trying to write it this way – Rilcon42 Aug 26 '19 at 02:23

1 Answers1

0

the only thing you need is "loop" the matColumnDef. -see that we use [matColumnDef] and {{element[col]}}

If your table is like

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

  <ng-container *ngFor="let col of displayedColumns" [matColumnDef]="col">
    <th mat-header-cell *matHeaderCellDef>{{col}}</th>
    <td mat-cell *matCellDef="let element"> {{element[col]}} </td>
  </ng-container>

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

You only need transform your data and indicate the displayedColumns. You can do in a ngOnInit()

ngOnInit() {
    const head = this.data.map(x => x.name)
    const data: any[] = [];
    this.data.forEach((x, index) => {
      Object.keys(x).forEach((k, index2) => {
        data[index2] = data[index2] || {}
        data[index2][head[index]] = x[k]

      })
    })
    this.displayedColumns=head;
    this.dataSource = data.slice(1); //I remove the first element that was the "header"
  } 

See in stackblitz

Eliseo
  • 29,422
  • 4
  • 13
  • 37