如何动态地向mat-table dataSource添加数据?

hus*_*ain 29 javascript angular-material2 angular angular5

我有来自后端的数据流,我看到它在控制台中打印现在我正在尝试将事件推送到dataSource其抛出错误dataSource未定义.有人可以帮助如何动态添加数据到物化表?

stream.component.html

<mat-table #table [dataSource]="dataSource"></mat-table>
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

小智 33

我找到了解决这个问题的方法,基本上如果你这样做:

this.dataSource.data.push(newElement); //Doesn't work

但如果你更换完整的阵列,那么它工作正常.所以你的最终代码必须是:

this.socket.on('newMessage', function(event) {
    const data = this.dataSource.data;
    data.push(event);
    this.dataSource.data = data;
});
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到问题 - > https://github.com/angular/material2/issues/8381

  • S/O 审核:请尝试在您的链接中添加一些上下文。简单地发布链接不会为您的答案增加价值。尝试仔细查看问题并总结答案中的相关内容。始终尽量做到必要的全面。如果你解释你的代码,也可能会让提问者受益。不幸的是,像这样的代码块会鼓励未来查看者的复制/粘贴行为。我们希望S/O用户在这里获得知识;所以,如果你有,请分享! (2认同)
  • 更干净,更优雅的方式:``this.dataSource.data = {... this.dataSource.data,event}'' (2认同)
  • this.dataSource.data = [ ...this.dataSource.data, 事件 ] (2认同)

and*_*tor 11

以下解决方案对我有用:

this.socket.on('newMessage', function(event) {
    this.dataSource.data.push(event);
    this.dataSource.data = this.dataSource.data.slice();
});
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是调用_updateChangeSubscription()MatTableDataSource 对象的方法:

this.socket.on('newMessage', function(event) {
    this.dataSource.data.push(event);
    this.dataSource._updateChangeSubscription();
});
Run Code Online (Sandbox Code Playgroud)

这种方法:

/** 订阅应该触发对表的呈现行进行更新的更改。当发生变化时,处理过滤器、排序和分页的当前状态以及提供的基本数据,并将其发送到表格进行渲染。*/

  • `this.dataSource.data = this.dataSource.data.slice();` 是不必要的,实际上可能会破坏 dataSource 与底层的连接。您可以使用“this.dataSource.data = this.dataSource.data;”来触发它,它不必(也不应该)通过切片/即新数组。 (3认同)
  • `this.dataSource._updateChangeSubscription()` 对我有用 (3认同)

小智 9

这是一个非常简单易行的解决方案:

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
}
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助:)


Eli*_*seo 7

文档

由于该表针对性能进行了优化,因此它不会自动检查数据数组的更改。相反,当在数据数组上添加、删除或移动对象时,您可以通过调用其 renderRows() 方法来触发对表的呈现行的更新。

因此,您可以使用 ViewChild 和 refreshRow()

@ViewChild('table', { static: true }) table;
  add() {
    this.dataSource.data.push(ELEMENT_DATA[this.index++]);
    this.table.renderRows();
  }
Run Code Online (Sandbox Code Playgroud)

我在stackblitz中整理了一个例子


nas*_*h11 5

您还可以使用 ES6 扩展运算符,或者concat如果您不使用 ES6+ 将dataSource数据分配给新数组。

在 ES6+ 中

this.socket.on('newMessage', function(event) {
    this.dataSource.data = [...this.dataSource.data, event];
});
Run Code Online (Sandbox Code Playgroud)

ECMAscript 版本 3+

this.socket.on('newMessage', function(event) {
    this.dataSource.data = this.dataSource.data.concat(event);
});
Run Code Online (Sandbox Code Playgroud)