I am using a mat-table to list the content of the users chosen languages. They can also add new languages using dialog panel. After they added a language and returned back.
Since you are using MatPaginator, you just need to do any change to paginator, this triggers data reload.
Simple trick:
this.paginator._changePageSize(this.paginator.pageSize);
This updates the page size to the current page size, so basically nothing changes, except the private _emitPageEvent()
function is called too, triggeing table reload.
Best way to do this is by adding an additional observable to your Datasource implementation.
In the connect method you should already be using Observable.merge
to subscribe to an array of observables that include the paginator.page, sort.sortChange, etc. You can add a new subject to this and call next on it when you need to cause a refresh.
something like this:
export class LanguageDataSource extends DataSource<any> {
recordChange$ = new Subject();
constructor(private languages) {
super();
}
connect(): Observable<any> {
const changes = [
this.recordChange$
];
return Observable.merge(...changes)
.switchMap(() => return Observable.of(this.languages));
}
disconnect() {
// No-op
}
}
And then you can call recordChange$.next()
to initiate a refresh.
Naturally I would wrap the call in a refresh() method and call it off of the datasource instance w/in the component, and other proper techniques.
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
export class LanguageComponent implemnts OnInit {
displayedColumns = ['name', 'native', 'code', 'leavel'];
user: any;
private update = new Subject<void>();
update$ = this.update.asObservable();
constructor(private authService: AuthService, private dialog: MatDialog) {}
ngOnInit() {
this.update$.subscribe(() => { this.refresh()});
}
setUpdate() {
this.update.next();
}
add() {
this.dialog.open(LanguageAddComponent, {
data: { user: this.user },
}).afterClosed().subscribe(result => {
this.setUpdate();
});
}
refresh() {
this.authService.getAuthenticatedUser().subscribe((res) => {
this.user = res;
this.teachDS = new LanguageDataSource(this.user.profile.languages.teach);
});
}
}
After reading Material Table not updating post data update #11638 Bug Report I found the best (read, the easiest solution) was as suggested by the final commentor 'shhdharmen' with a suggestion to use an EventEmitter.
This involves a few simple changes to the generated datasource class
ie) add a new private variable to your datasource class
import { EventEmitter } from '@angular/core';
...
private tableDataUpdated = new EventEmitter<any>();
and where I push new data to the internal array (this.data), I emit an event.
public addRow(row:myRowInterface) {
this.data.push(row);
this.tableDataUpdated.emit();
}
and finally, change the 'dataMutation' array in the 'connect' method - as follows
const dataMutations = [
this.tableDataUpdated,
this.paginator.page,
this.sort.sortChange
];
This is working for me:
dataSource = new MatTableDataSource<Dict>([]);
public search() {
let url = `${Constants.API.COMMON}/dicts?page=${this.page.number}&` +
(this.name == '' ? '' : `name_like=${this.name}`);
this._http.get<Dict>(url).subscribe((data)=> {
// this.dataSource = data['_embedded'].dicts;
this.dataSource.data = data['_embedded'].dicts;
this.page = data['page'];
this.resetSelection();
});
}
So you should declare your datasource instance as MatTableDataSource
// this is the dataSource
this.guests = [];
this.guests.push({id: 1, name: 'Ricardo'});
// refresh the dataSource this.guests = Array.from(this.guest);