How to set up a material angular table with key and values separated into different arrays in one json response?

Viewed 586

I was able to create a material table using this link. But it would work if the data array/ data response has a key-value pair.

I am trying to create a table using material angular using the following dataset. The first array would be the table header and all the other subsequent arrays would be table rows.

Json Response

"data":[
      [
         "id",
         "name",
         "email",
         "purpose",
         "programme",
         "year",
         "language",
         "comments",
         "status"
      ],
      [
         "1",
         "Safa",
         "neerupeeru@mail.ee",
         "{motivation=null, skills=[], salary=null, status=null, statusdate=null}",
         "Software Engineering",
         "2016",
         "Estonian",
         "In need of correcting a dangling participle.",
         "null"
      ],
      [
         "2",
         "Jack",
         "jackie222@mail.ee",
         "{motivation=family, skills=[java], salary=null, status=Active, statusdate=null}",
         "Software Engineering",
         "2016",
         "Java",
         "In need of correcting a experience.",
         "Active"
      ],
      [
         "3",
         "Manny",
         "moonie123@mail.ee",
         "{motivation=hardworking, skills=[python], salary=null, status=pending, statusdate=null}",
         "Software Engineering",
         "2016",
         "Python",
         "to understand the workflow.",
         "pending"
      ],
   ]

Component.ts

  //subscribed to api and storing dataset into "rows" variable.
   this.rows = data.data;
   this.columnName = data.data[0]; //stores the column names (data[0]
   this.dataValues = data.data[1]; //do not want to store every other data indivually.

Attempt HTML

<div class="example-container mat-elevation-z8" *ngIf="rows?.length>0;">
  <table mat-table [dataSource]="dataSource">

    <ng-container *ngFor="let col of rows[0]" [matColumnDef]="col">
      <th mat-header-cell  *matHeaderCellDef class ="headerPadding"> <h3><b>{{ col }}</b></h3></th>
      <td mat-cell *matCellDef="let element" class="tablePadding"> <b>{{element}} </b></td>
    </ng-container>   

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

</div>

With the HTML above I am able to display the headers properly. However, I am not able to display the subsequent data as rows. Hence data1... data[2].... data[3]...

Any ideas/advice is greatly appreciated.

Attempt 2 HTML

<table style="width:100%">
  <tr>
    <th *ngFor="let col of rows[0]">{{col}}</th>   
  </tr>
  <tr>
    <td *ngFor="let dataOne of rows[1]">{{dataOne }}</td>
  </tr>
 <tr>
    <td *ngFor="let dataTwo of rows[2]">{{dataTwo }}</td>
  </tr> 
</table>

With this, I am able to display the header and data properly. However, this is not dynamic. If data respond with more than 4 data. This logic will not be displaying those values.

1 Answers

This way you can iterate over data source.

<table mat-table [dataSource]="dataValues" class="mat-elevation-z8">
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>

  <!-- Columns loop -->
  <ng-container *ngFor="let col of columnName; let i = index"  matColumnDef="{{col}}">
    <th mat-header-cell *matHeaderCellDef> {{col}} </th>
    <td mat-cell *matCellDef="let element"> {{element[i]}} </td>
  </ng-container>


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

Component.ts

  this.dataValues = ELEMENT_DATA.slice(1);

Other solution is to transform the data as @JSmith say, but, if the array is too big, transform the data could be a performance problem.

Related