バックエンドからのデータストリーミングがあり、コンソールに印刷されていることがわかります。イベントを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;
}
基本的にあなたがそうすれば、私はこの問題の解決策を見つけました:
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
次の解決策はAngular 5.2.および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();
});
この方法:
/ **テーブルのレンダリングされた行の更新をトリガーする変更をサブスクライブします。変更が発生したら、提供された基本データとともにフィルター、ソート、およびページネーションの現在の状態を処理し、レンダリングのためにテーブルに送信します。 * /
docs から
テーブルはパフォーマンスを最適化するため、データ配列への変更を自動的にチェックしません。代わりに、オブジェクトがデータ配列で追加、削除、または移動されたときに、renderRows()メソッドを呼び出すことで、テーブルのレンダリングされた行の更新をトリガーできます。
そのため、ViewChildとrefreshRow()を使用できます
@ViewChild('table', { static: true }) table
add() {
this.dataSource.data.Push(ELEMENT_DATA[this.index++])
this.table.renderRows()
}
stackblitz に簡単な例を示します
これは非常にシンプルで簡単なソリューションです。
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
}
これが役立つことを願っています:)
行の選択を作成し、行データに対して何らかのアクションを適用するときに、同じ問題が発生しました。あなたの問題に対するこの解決策
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;
});
}
これがあなたの助けになることを願っています。質問がある場合は、pingを実行してください。
別の配列にプッシュしてdataSource
データに割り当てるのではなく、ES6スプレッド演算子を使用するか、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);
});