[Fixed] Binding material table to api node table

Issue

I want to connect rest api data source to material table. This works for simple table but material table doesn’t show any data.

This is the markup for simple table that works fine:

<!-- simple table -->
<table border="1">
    <thead>
        <tr>
            <th>id</th>
            <th>description</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let x of list_product">
            <td>{{x.id}}</td>
            <td>{{x.description}}</td>
        </tr>
    </tbody>
</table>
<!-- end of simple table -->

But this markup for a material table doesn’t show the data:

<!-- material table -->
<table mat-table>
    <!-- Position Column -->
    <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef> No. </th>
        <td mat-cell *matCellDef="let x of list_product"> {{x.id}} </td>
    </ng-container>

    <!-- Name Column -->
    <ng-container matColumnDef="description">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let x of list_product"> {{x.description}} </td>
    </ng-container>

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

This is my Typescript code that call table from node:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { analyzeAndValidateNgModules } from '@angular/compiler';

@Component({
    selector: 'app-basic',
    templateUrl: './basic.component.html',
    styleUrls: ['./basic.component.scss']
})
export class BasicComponent implements OnInit {

    public list_product:any=[];
    displayedColumns: string[] = ['id', 'description'];

    constructor(private http:HttpClient) { }

    ngOnInit(): void {
        this.get_data();
    }

    get_data()
    {
        this.http.get("http://localhost:3000/listp").subscribe(
            (res)=>{ 
                for(var i=0;i<res['length'];i++){
                    this.list_product.push(res[i]);
                }
            }//end res
        )
    }
}

Solution

Your simple table and material table works differently. Therefore –

  1. in your template, you need to bind list_product to the dataSource property of mat-table
  2. in your component code, you need to replace the list_product each time you receive a new response – populating list_product with items one by one will not update the table’s dataSource.

Modify your table as –

<table mat-table [dataSource]="list_product">
    <!-- Position Column -->
    <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef> No. </th>
        <td mat-cell *matCellDef="let product"> {{product.id}} </td>
    </ng-container>

    <!-- Name Column -->
    <ng-container matColumnDef="description">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let product"> {{product.description}} </td>
    </ng-container>

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

and change the get_data() method to –

get_data(){
    this.http.get<any>("http://localhost:3000/listp").subscribe(
            res => this.list_product = res
        );
}

For further details, check the documentation

Leave a Reply

(*) Required, Your email will not be published