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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:52:53  来源:igfitidea点击:

How to add data dynamically to mat-table dataSource?

javascriptangularangular-material2angular5

提问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.3Angular 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 我。