How to add data dynamically to mat-table dataSource?
Solution 1
I have found a solution for this problem, basically if you do:
this.dataSource.data.push(newElement); //Doesn't work
But if you replace the complete array then it works fine. So your final code must be :
this.socket.on('newMessage', function(event) {
const data = this.dataSource.data;
data.push(event);
this.dataSource.data = data;
});
You can see the issue here -> https://github.com/angular/material2/issues/8381
Solution 2
The following solution worked for me:
this.socket.on('newMessage', function(event) {
this.dataSource.data.push(event);
this.dataSource.data = this.dataSource.data.slice();
});
Another solution would be calling the _updateChangeSubscription()
method for the MatTableDataSource object:
this.socket.on('newMessage', function(event) {
this.dataSource.data.push(event);
this.dataSource._updateChangeSubscription();
});
This method:
/** Subscribe to changes that should trigger an update to the table's rendered rows. When the changes occur, process the current state of the filter, sort, and pagination along with the provided base data and send it to the table for rendering. */
Solution 3
Here is a very simple and easy solution:
displayedColumns = ['ticketNum', 'assetID', 'severity', 'riskIndex', 'riskValue', 'ticketOpened', 'lastModifiedDate', 'eventType'];
dataSource: any[] = [];
constructor() {
}
ngOnInit() {
}
onAdd() { //If you want to add a new row in the dataSource
let model = { 'ticketNum': 1, 'assetID': 2, 'severity': 3, 'riskIndex': 4, 'riskValue': 5, 'ticketOpened': true, 'lastModifiedDate': "2018-12-10", 'eventType': 'Add' }; //get the model from the form
this.dataSource.push(model); //add the new model object to the dataSource
this.dataSource = [...this.dataSource]; //refresh the dataSource
}
Hope this will help :)
Solution 4
from the docs
Since the table optimizes for performance, it will not automatically check for changes to the data array. Instead, when objects are added, removed, or moved on the data array, you can trigger an update to the table's rendered rows by calling its renderRows() method.
So, you can use ViewChild, and refreshRow()
@ViewChild('table', { static: true }) table;
add() {
this.dataSource.data.push(ELEMENT_DATA[this.index++]);
this.table.renderRows();
}
I put together an example in stackblitz
Solution 5
You could also use the ES6 spread operator or concat
if you are not using ES6+ to assign the dataSource
data to a new array.
In ES6+
this.socket.on('newMessage', function(event) {
this.dataSource.data = [...this.dataSource.data, event];
});
ECMAscript version 3+
this.socket.on('newMessage', function(event) {
this.dataSource.data = this.dataSource.data.concat(event);
});
hussain
Updated on June 02, 2020Comments
-
hussain almost 4 years
I have data streaming from backend and i see it printing in console now i am trying to push event to
dataSource
its throwing error dataSource is not defined. Can someone help how to dynamically add data to materialize table ?stream.component.html
<mat-table #table [dataSource]="dataSource"></mat-table>
stream.component.ts
import { Component, OnInit } from '@angular/core'; import { StreamService } from '../stream.service'; import { MatTableDataSource } from '@angular/material'; import * as io from 'socket.io-client'; @Component({ selector: 'app-stream', templateUrl: './stream.component.html', styleUrls: ['./stream.component.css'] }) export class StreamComponent implements OnInit { displayedColumns = ['ticketNum', "assetID", "severity", "riskIndex", "riskValue", "ticketOpened", "lastModifiedDate", "eventType"]; dataSource: MatTableDataSource < Element[] > ; socket = io(); constructor(private streamService: StreamService) {}; ngOnInit() { this.streamService.getAllStream().subscribe(stream => { this.dataSource = new MatTableDataSource(stream); }); this.socket.on('newMessage', function(event) { console.log('Datasource', event); this.dataSource.MatTableDataSource.filteredData.push(event); }); } } export interface Element { ticketNum: number; ticketOpened: number; eventType: string; riskIndex: string; riskValue: number; severity: string; lastModifiedDate: number; assetID: string; }