Material Table not updating post data update
See original GitHub issueBug, feature request, or proposal:
The Material Table used in my application is not updating after data is fetched from the backend. Initially, the DataSource has no data. Using console logs I have determined that connect is called on the DataSource ‘before’ 'the subscribe to the graphql query returns (initiated in the constructor of the DataSource). Hence the initial view of the table is empty. But when the data arrives, the data field in the DataSource is updated, and since the connect method provides the data as an observable, the table should update/refresh. This is not happening. Interestingly, the pagination support in the mat-table (i.e., mat-paginator) is updating to show ‘1-4 of 4’ - which is correct, as 4 items are returned from the backend in my test environment, but the table does not show any rows.
What is the expected behavior?
Table should update and show the rows of data that have been provided to it as an observable.
What is the current behavior?
Table does not update with dynamic backend data. Works fine with static data built into the angular app.
What are the steps to reproduce?
Providing a StackBlitz reproduction is the best way to share your issue.
StackBlitz starter: https://goo.gl/wwnhMV
Trying to figure this out, and will try to update ASAP.
What is the use-case or motivation for changing an existing behavior?
I think behavior is broken
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
Angular CLI: 6.0.3 Node: 9.11.1 OS: linux x64 Angular: 6.0.2 … animations, cdk, common, compiler, compiler-cli, core, forms … http, language-service, platform-browser … platform-browser-dynamic, router
Package Version
@angular-devkit/architect 0.6.3 @angular-devkit/build-angular 0.6.1 @angular-devkit/build-optimizer 0.6.1 @angular-devkit/core 0.0.29 @angular-devkit/schematics 0.6.3 @angular/cli 6.0.3 @angular/material 6.2.0 @ngtools/webpack 6.0.1 @schematics/angular 0.6.3 @schematics/update 0.6.3 rxjs 6.1.0 typescript 2.7.2 webpack 4.6.0
Have also tried with @angular/material@6.0.2
Is there anything else we should know?
Some code snippets: =====DataSource=====================
export class FleetTableDataSource extends DataSource<FleetTableItem> {
data: FleetTableItem[] = [];
loading: boolean = true;
systems: any[] = [];
constructor(private paginator: MatPaginator, private sort: MatSort, private fleetDataSvc: FleetDataService) {
super();
console.log("constructorr " + new Date())
this.fleetDataSvc.getAllSystems().subscribe(({ data }) => {
this.loading = data.loading;
this.systems = data.allSystems.edges;
for (let system of this.systems) {
var f = <FleetTableItem>{};
f.x = system.node.x;
f.a = system.node.A.a;
f.b = system.node.A.b;
f.y = system.node.y;
f.z = system.node.B.d + "/" + system.node.B.e;
this.data.push(f);
}
console.log("Data has arrived " + new Date());
});
connect(): Observable<FleetTableItem[]> {
console.log("connect called " + new Date());
// Combine everything that affects the rendered data into one update
// stream for the data-table to consume.
const dataMutations = [
observableOf(this.data),
this.paginator.page,
this.sort.sortChange
];
// Set the paginators length
this.paginator.length = this.data.length;
return merge(...dataMutations).pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data]));
}));
}
======= FleetDataService ===========
const allSystemsSummary = gql`
query Systems_Summary {
allSystems {
edges {
node {
A {
a
b
}
id
x
y
B {
d
e
}
}
}
}
}`;
@Injectable()
export class FleetDataService {
constructor(private apollo: Apollo) {
}
getAllSystems(): Observable<ApolloQueryResult<any>> {
return this.apollo.watchQuery<any>({
query: allSystemsSummary
}).valueChanges;
}
}
Issue Analytics
- State:
- Created 5 years ago
- Comments:11 (2 by maintainers)
Top GitHub Comments
Internally what happens is this. The table called
connect
to retrieve a stream from the data source. When the data source emits an array on that stream, the table re-renders its rows.In your case, you are adding to the array, but not emitting anything new so the table is not signaled to re-render.
Here’s an example of a working demo. The change I made was adding a data stream that emits your data. When new data is added, we take a copy of the old data, push a new value, and emit that new array on the stream.
https://stackblitz.com/edit/angular-material2-issue-yzhsml?file=app/data-table-datasource.ts
Please use our issue queue for bugs and features. Unfortunately we don’t always have the bandwidth to dive into investigations for troubleshooting. You may have better help if you ask our community is places like StackOverflow or Gitter