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 */
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";
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,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With