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

问题描述 投票:16回答:4

我有从后端的数据流,我看到它在控制台打印现在我试图将事件推送到dataSource它的投掷错误dataSource没有定义。有人可以帮助如何动态添加数据到物化表?

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;
}
javascript angular angular-material2 angular5
4个回答
28
投票

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

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;
});

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


2
投票

来自docs

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

所以,你可以使用ViewChild和refreshRow()

@ViewChild('table', { static: true }) table
  add() {

    this.dataSource.data.push(ELEMENT_DATA[this.index++])
    this.table.renderRows()
  }

我在stackblitz中举了一个简单的例子


2
投票

以下解决方案适用于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();
});

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

this.socket.on('newMessage', function(event) {
    this.dataSource.data.push(event);
    this.dataSource._updateChangeSubscription();
});

这个方法:

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


1
投票

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

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
}

希望这会有所帮助:)


0
投票

在创建选择行并在行数据上应用某些操作时,我遇到了同样的问题。这个问题的解决方案

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;
    });
  }

希望这会帮助你 。如果你有任何疑问,请给我打电话。


0
投票

如果您没有使用ES6 +将dataSource数据分配给新数组,我们可以使用ES6扩展运算符或concat,而不是推入单独的数组然后将其分配给dataSource数据。

在ES6 +中

this.socket.on('newMessage', function(event) {
    this.dataSource.data = [...this.dataSource.data, event];
});

ECMAscript版本3+

this.socket.on('newMessage', function(event) {
    this.dataSource.data = this.dataSource.data.concat(event);
});
© www.soinside.com 2019 - 2024. All rights reserved.