Javascript 如何将数据动态添加到 mat-table 数据源?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47581267/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add data dynamically to mat-table dataSource?
提问by hussain
I have data streaming from backend and i see it printing in console now i am trying to push event to dataSourceits throwing error dataSource is not defined. Can someone help how to dynamically add data to materialize table ?
我有来自后端的数据流,我看到它在控制台中打印,现在我试图将事件推送到dataSource它的抛出错误数据源未定义。有人可以帮助如何动态添加数据以实现表吗?
stream.component.html
流.component.html
<mat-table #table [dataSource]="dataSource"></mat-table>
stream.component.ts
流.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;
}
回答by Jose Luis
I have found a solution for this problem, basically if you do:
我已经找到了解决这个问题的方法,基本上如果你这样做:
this.dataSource.data.push(newElement); //Doesn't work
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
您可以在此处查看问题-> https://github.com/angular/material2/issues/8381
回答by andreivictor
The following solution worked for me on Angular 5.2.3and Angular Material 5.1.1:
以下解决方案在Angular 5.2.3和Angular Material 5.1.1上对我有用:
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:
另一种解决方案是调用_updateChangeSubscription()MatTableDataSource 对象的方法:
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. */
/** 订阅应该触发对表的呈现行进行更新的更改。当发生变化时,处理过滤器、排序和分页的当前状态以及提供的基本数据,并将其发送到表格进行渲染。*/
回答by Eliseo
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.
由于该表针对性能进行了优化,因此它不会自动检查数据数组的更改。相反,当在数据数组上添加、删除或移动对象时,您可以通过调用其 renderRows() 方法来触发对表的呈现行的更新。
So, you can use ViewChild, and refreshRow()
因此,您可以使用 ViewChild 和 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
我在stackblitz中整理了一个例子
回答by SKB
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 :)
希望这会有所帮助:)
回答by nash11
You could also use the ES6 spread operator or concatif you are not using ES6+ to assign the dataSourcedata to a new array.
您也可以使用 ES6 扩展运算符,或者concat如果您不使用 ES6+ 将dataSource数据分配给新数组。
In ES6+
在 ES6+ 中
this.socket.on('newMessage', function(event) {
this.dataSource.data = [...this.dataSource.data, event];
});
ECMAscript version 3+
ECMAscript 版本 3+
this.socket.on('newMessage', function(event) {
this.dataSource.data = this.dataSource.data.concat(event);
});
回答by Ezri Y
For me, nothing of these answers didn't work. I had an observable that I subscribe to get new data. the only solution that works for me was:
对我来说,这些答案没有一个不起作用。我有一个可观察的对象,我订阅它以获取新数据。对我有用的唯一解决方案是:
this.dataService.pointsNodesObservable.subscribe((data) => {
this.dataSource = new InsertionTableDataSource(this.paginator, this.sort, this.dataService);
this.dataSource.data = data;
});
render like a charm!
像魅力一样呈现!
回答by Vikas Kumar
I was stuck in same problem while creating select row and apply some action over rows data. This solution for your problem
在创建选择行并对行数据应用一些操作时,我遇到了同样的问题。此解决方案可解决您的问题
imports..................
import { MatTableDataSource } from '@angular/material';
@component({ ...
export class StreamComponent implements OnInit {
// Initialise MatTableDataSource as empty
dataSource = new MatTableDataSource<Element[]>();
constructor() {}
...
// if you simply push data in dataSource then indexed 0 element remain undefined
// better way to do this as follows
this.dataSource.data = val as any;
// for your problem
ngOnInit() {
// ** important note .... I am giving solution assuming the subscription data is array of objects. Like in your case stream and in second event(parameter as callback)
this.streamService.getAllStream().subscribe(stream => {
// do it this way
this.dataSource.data = stream as any;
// note if you simply put it as 'this.dataSource.data = stream' then TS show you error as '[ts] Type 'string' is not assignable to type '{}[]''
});
this.socket.on('newMessage', (event) => {
console.log('Datasource', event);
// for this value
// this.dataSource.MatTableDataSource.filteredData.push(event); // I couldn't get what you are doing here
// SO try to explain what you are getting in this callback function val as event parameter ?????????????????
// but you can get it this ways
this.dataSource.filteredData = event as any;
});
}
Hope this will help you . If you have any question just ping me.
希望这会帮助你 。如果您有任何问题,请 ping 我。

