Как динамически добавлять данные в файл данных mat-table?
У меня есть потоковая передача данных из бэкэнд, и я вижу, что она печатает на консоли. Теперь я пытаюсь dataSource
событие в dataSource
его данные ошибки throwingSource не определены. Может кто-нибудь помочь, как динамически добавлять данные в таблицу материализации?
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;
}
Ответы
Ответ 1
Я нашел решение этой проблемы, в основном, если вы это сделаете:
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
Следующее решение помогло мне с 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();
});
Другим решением будет вызов метода _updateChangeSubscription()
для объекта MatTableDataSource:
this.socket.on('newMessage', function(event) {
this.dataSource.data.push(event);
this.dataSource._updateChangeSubscription();
});
Этот метод:
/** Подпишитесь на изменения, которые должны инициировать обновление отображаемых строк таблицы. Когда изменения происходят, обрабатывают текущее состояние фильтра, сортировки и разбивки на страницы вместе с предоставленными базовыми данными и отправляют их в таблицу для визуализации. */
Ответ 3
Вот очень простое и легкое решение:
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
}
Надеюсь, это поможет :)
Ответ 4
из документов
Поскольку таблица оптимизируется по производительности, она не будет автоматически проверять изменения в массиве данных. Вместо этого, когда объекты добавляются, удаляются или перемещаются в массив данных, вы можете инициировать обновление отображаемых строк таблицы, вызывая его метод renderRows().
Таким образом, вы можете использовать ViewChild и refreshRow()
@ViewChild('table', { static: true }) table;
add() {
this.dataSource.data.push(ELEMENT_DATA[this.index++]);
this.table.renderRows();
}
Я собрал пример в stackblitz
Ответ 5
Вместо того, чтобы вставлять отдельный массив и затем назначать его данным dataSource
, мы могли бы просто использовать оператор распространения ES6 или concat
, если вы не используете ES6+, чтобы назначить данные 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);
});
Ответ 6
Я столкнулся с одной проблемой при создании строки выбора и применил какое-то действие по данным строк. Это решение для вашей проблемы
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;
});
}
Надеюсь, что это поможет вам. Если у вас есть вопрос, просто пингуйте меня.
Ответ 7
export class PedidoComponent implements OnInit {
form: FormGroup;
pedidos: Pedido[] = [];
ngOnInit() {
this.form = this.fb.group({
codigo: new FormControl(null, Validators.required),
produto: new FormControl(null, Validators.required),
quantidade: new FormControl(null, Validators.required),
valorUnitario: new FormControl({ value: '0,00', disabled: true }),
valorTotal: new FormControl({ value: '0,00', disabled: true })
});
}
addProduto() {
this.pedidos.push(this.form.getRawValue());
this.pedidos = [...this.pedidos];
}
}
Ответ 8
https://codingthesmartway.com/angular-material-part-4-data-table/
Пожалуйста, обратитесь по этой ссылке, это работает как шарм для меня
Ответ 9
Для меня ничего из этих ответов не сработало.
У меня было заметное, что я подписываюсь, чтобы получать новые данные.
единственное решение, которое работает для меня, было:
this.dataService.pointsNodesObservable.subscribe((data) => {
this.dataSource = new InsertionTableDataSource(this.paginator, this.sort, this.dataService);
this.dataSource.data = data;
});
сделать как шарм!