Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Instance of a Mat-Table, If we have multiple tables in the component

Am struck with some issue. I have a component in Angular 6 where am generating multiple Mat-Tables with Data. Am using the ng-for loop in the div tag to loop through all the Mat-Table Data sources. Later am trying to add a new row to the table . Till here it is fine, But am not able to get the Instance of the table for which this Add Row function is clicked. In .ts fenter code hereile with the help of View-Child am always getting the instance of the 1st table only. I would like to get the instance of all the table, with which I will call the render rows function to refresh that selected MatTable in the view

Pasted Sample code for the View and TS File. Note Add is not working now.

   <div *ngFor="let data of ViewContent">
<button (click)="addElement(event,data?.tableValues,displayedColumns)">Add element</button> <br />
<table   #testTable mat-table [dataSource]="data?.tableValues">

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

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

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

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



<!-- Copyright 2019 Google Inc. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license -->

</div>



import {DataSource} from '@angular/cdk/collections';
import {Component,OnInit,ViewChild} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs';
import  DalContentdata from 'Content.json';
import { MatTable } from '@angular/material';

@Component({
  selector: 'cdk-table-basic-example',
  styleUrls: ['cdk-table-basic-example.css'],
  templateUrl: 'cdk-table-basic-example.html',
})
export class CdkTableBasicExample implements OnInit  {
   ViewContent: Object;
   displayedColumns: string[] = ['Col1','Col2','Col3'];

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

  ngOnInit() {
    this.ViewContent =  [
    {
      "title":"abc",
      "tableValues": [
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        }
      ]
    },
    {
       "title":"abc",
      "displayColumns": "Col1,Col2,Col3",
      "tableValues": [
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        }
      ]
    },
    {
       "title":"abc",
      "displayColumns": "Col1,Col2,Col3",
      "tableValues": [
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        },
        {
          "Col1": "Apple",
          "Col2": "Mango",
          "Col3": "Orange"
        }
      ]
    }
  ];
  }


  addElement(event, title, tableDataSource, displayColumns) {
        console.log('beforeAdd', tableDataSource);
    tableDataSource.push({
      Col1: 'Test',Col2:'Test',Col3:'Test'
    })
     console.log('afteradd', tableDataSource);
     this.table.renderRows();

    console.log('afteradd', tableDataSource);
  }


}


/**  Copyright 2019 Google Inc. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license */
like image 982
Santosh Shiva Kumar Avatar asked Nov 25 '25 02:11

Santosh Shiva Kumar


2 Answers

I had a similar issue and resolved it by using ViewChildren rather than ViewChild.

I initially had:

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

and to call renderRows on it, I was calling

this.table.renderRows();

However, I then needed another table in the same component, so my code changed to:

@ViewChildren(MatTable) table !: QueryList<MatTable<string>>;

and

this.table.first.renderRows();
this.table.last.renderRows();

With first and last being properties of queryList. https://angular.io/api/core/QueryList#properties

Make sure you're importing MatTable

import { MatTable } from "@angular/material/table";
like image 66
Chishty Avatar answered Nov 28 '25 02:11

Chishty


you should use ViewChild.

html: let's assume that your tables running inside a for loop with and index variable named i:

  <table id="testTable{{i}}" [dataSource]="yourDataSource"><!--data source can be set from ts as well-->

ts:

@ViewChild('testTable1') matTable1: MatTable<any>;
  @ViewChild('testTable2') matTable2: MatTable<any>;
  @ViewChild('testTable3') matTable3: MatTable<any>;

or of course just can just use an array.

don't forget to import it, and you will prefer to use AfterViewInit lifecycle hook

  ngAfterViewInit() {
//    this.matTable...
  }

Edit:

if you wish to refresh your data source

this.matTable.dataSource=[...this.data]

you can just pass new array (with a new reference) and it will trigger the data change and you data table will refresh

If you wish to create a unic ID for every table using for,

like image 43
Or Yaacov Avatar answered Nov 28 '25 02:11

Or Yaacov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!