2

I have below json and want to render in material table in angular

var res = '[
  {
    "DynamicName": "xyz",
    "DynamicLevel": "xyz",
    "DynamicLevel": "xyz",
    "DynamicLevel": "xyz",
    "dynamic": "xyz"
  },
  {
    "DynamicName": "xyz",
    "DynamicLevel": "xyz",
    "DynamicLevel": "xyz",
    "DynamicLevel": "xyz",
    "dynamic": "xyz"
  },
  {
    "DynamicName": "xyz",
    "DynamicLevel": "xyz",
    "DynamicLevel": "xyz",
    "DynamicLevel": "xyz",
    "dynamic": "xyz"
  }]';

In second response this json will be like below

var res = '[
      {
        "DynamicCity": "xyz",
        "DynamicCountry": "xyz",
        "DynamicState": "xyz",
        "DynamicRegion": "xyz",
        "dynamic": "xyz"
      },
      {
        "DynamicCity": "xyz",
        "DynamicCountry": "xyz",
        "DynamicState": "xyz",
        "DynamicRegion": "xyz",
        "dynamic": "xyz"
      },
      {
        "DynamicCity": "xyz",
        "DynamicCountry": "xyz",
        "DynamicState": "xyz",
        "DynamicRegion": "xyz",
        "dynamic": "xyz"
      }]';

this data need to render in material table I have tried like this

// properties of the class
displayedColumns: string[];//columns should be create dynamically
dataSource = res;

    <table mat-table [dataSource]="dataSource | keyvalue" class="mat-elevation-z8">
      <ng-container matColumnDef="key">
        <th mat-header-cell *matHeaderCellDef> {{element.key}}</th>
        <td mat-cell *matCellDef="let element"> {{element.value}} </td>
      </ng-container>  
    
      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>

I need output like below

enter image description here

Here, dynamic column means in each api call we get different data for this column names so it will be changed every api call so I am not able to bind it to material table. Please help me to solve this issue of binding json data to material table. reference URLs:-

  1. Angular mat-table display dynamic key value pair in each row
  2. https://www.interfacecreator.com/2018/10/angular-material-table-dynamic.html

4 Answers 4

2

I created a Stackblitz for you. This should work with any lists with objects with simple values (will take the keys from the first object, so all the objects needs to be the same for the current list (no way around this without creating separate tables)): https://stackblitz.com/edit/angular-pqgny8?file=src/app/table-basic-example.html

HTML:

<table *ngIf="dataSource && displayedColumns" mat-table [dataSource]="dataSource" class="mat-elevation-z8">

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

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

TS:

getData() {
this.dataSource = ELEMENT_DATA; // ELEMENT_DATA is the data from your backend
this.displayedColumns = Object.keys(this.dataSource[0]).map(k => k)

}

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for trying to help. I have given vote to your answer also.
1
 import { Component,OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.sass']
})
export class AppComponent implements OnInit {
  title = 'jsonDemo';

  ELEMENT_DATA1 = [
    { 'DynamiCCity': 'Hydrogen' , 'DynamicCountry' : 'Country', 'DynamicState' : 'State' , 'DynamicRegion' :'DynamicRegion' , 'dynamic' :'dynamic' },
    { 'DynamiCCity': 'Hydrogen 1' , 'DynamicCountry' : 'Country 1', 'DynamicState' : 'State 1' , 'DynamicRegion' :'DynamicRegion 1' , 'dynamic':'dynamic 1' },
  ];

  displayedColumns: string[] = [];
  dataSource1 = this.ELEMENT_DATA1;
 
  ngOnInit(): void
  {
    this.displayedColumns = Object.getOwnPropertyNames(this.ELEMENT_DATA1[0]);
  }
}


<h2>Demo</h2>

<style>
  table {
  width: 100%;
}
</style>


<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <ng-container *ngFor="let item of displayedColumns" matColumnDef="{{item}}">
    <th mat-header-cell *matHeaderCellDef> {{item}} </th>
    <td mat-cell *matCellDef="let element"> {{ element[item] }}</td>
  </ng-container>

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


<router-outlet></router-outlet>

I Hope Above Code is Working Demo of your Issue. It will work as expected.

Comments

1

Html

<div class="demo-button-container">
  <button mat-raised-button (click)="addData()" class="demo-button">
    Add data
  </button>
  <button
      mat-raised-button
      [disabled]="!dataSource.length"
      (click)="removeData()"
      class="demo-button">
    Remove data
  </button>
</div>

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 demo-table">
  <!-- Position Column -->
 <ng-container [matColumnDef]="col" *ngFor="let col of displayedColumns">
      <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>

ts

import {Component, ViewChild} from '@angular/core';
import {MatTable} from '@angular/material/table';

export interface dynElement {
  DynamicName: string,
  DynamicLevel_1: string,
  DynamicLevel_2:string,
  DynamicLevel_3:string,
  dynamic:string
}

const ELEMENT_DATA: any [] = [
  {
    DynamicName: "xyz",
    DynamicLevel_1: "xyz",
    DynamicLevel_2: "xyz",
    DynamicLevel_3: "xyz",
    dynamic: "xyz"
  },
  {
    DynamicName: "xyz",
    DynamicLevel_1: "xyz",
    DynamicLevel_2: "xyz",
    DynamicLevel_3: "xyz",
    dynamic: "xyz"
  },
  {
    DynamicName: "xyz",
    DynamicLevel_1: "xyz",
    DynamicLevel_2: "xyz",
    DynamicLevel_3: "xyz",
    dynamic: "xyz"
  },
  {
    DynamicName: "xyz",
    DynamicLevel_1: "xyz",
    DynamicLevel_2: "xyz",
    DynamicLevel_3: "xyz",
    dynamic: "xyz"
  },
]
@Component({
  selector: 'table-dynamic-array-data-example',
  styleUrls: ['table-dynamic-array-data-example.css'],
  templateUrl: 'table-dynamic-array-data-example.html',
})
export class TableDynamicArrayDataExample {
  
  // your Object Key Object.keys(obj)

  displayedColumns: string[] = [...Object.keys(ELEMENT_DATA[0])];
  dataSource = [...ELEMENT_DATA]; // you can pass your data from backend here

  @ViewChild(MatTable) table: MatTable<any>;

  addData() {
    const randomElementIndex = Math.floor(Math.random() * ELEMENT_DATA.length);
    this.dataSource.push(ELEMENT_DATA[randomElementIndex]);
    this.table.renderRows();
  }

  removeData() {
    this.dataSource.pop();
    this.table.renderRows();
  }
}

demo in stackblitz

7 Comments

displayedColumns you have created static columns. in my case it will be dynamic bro
Maybe this can helpe u ; )
You welcome. Did this answer your question?
Can you share the link? from the answer you found.
Thanks for trying to help. I have given vote to your answer also.
|
1

https://material.angular.io/components/table/examples :

<table mat-table [dataSource]="data" class="mat-elevation-z8">
 <ng-container [matColumnDef]="column" *ngFor="let column of 
 displayedColumns">
  <th mat-header-cell *matHeaderCellDef> {{column}} </th>
  <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
 </ng-container>
 <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
 <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.