Reputation: 725
I would be glad to have a bit of help on my current bug as I'm trying to get a solution since several days. I want to display a search result, which can have a few hundreds of items in it. I'm using a mat-table
with a mat-paginator
to avoid too many items on a single page. The code looks like this :
<mat-paginator #paginator [pageSize]="pageSize" [length]="resultsCount">
</mat-paginator>
<table [dataSource]="itemsDS" mat-table matSort matSortDisableClear>
<!-- rows / columns defs, nothing too fancy -->
</table>
And TS :
export class TableComponent implements OnInit {
public itemsColumns: Array<string> = ["id", "name"];
public itemsDS: MatTableDataSource<{
id: number;
name: string;
}> = new MatTableDataSource<{ id: number; name: string }>();
@ViewChild(MatPaginator, { static: false }) set paginator(
paginator: MatPaginator
) {
this.itemsDS.paginator = paginator;
}
@ViewChild(MatSort, { static: false }) set sort(sort: MatSort) {
this.itemsDS.sort = sort;
}
constructor(private router: Router, private itemsService: ItemsService) {}
ngOnInit() {
console.log("Initializing items data");
this.itemsDS.data = this.itemsService.items;
}
ngAfterViewInit() {
if (this.itemsDS.paginator && this.itemsService.currentIndex > -1) {
console.log("Restoring page index " + this.itemsService.currentIndex);
this.itemsDS.paginator.pageIndex = this.itemsService.currentIndex;
}
}
ngOnDestroy() {
const currentPage = this.itemsDS.paginator.pageIndex;
console.log("Saving page index on destroy " + currentPage);
this.itemsService.currentIndex = currentPage;
}
// a few other functions like getters
}
This saves onDestroy
the current page when the user is navigating to one of the element and restore this last viewed page whenever the user comes back to the search results.
This is working fine, but only when the saved page index has the value 0
. Whenever the user navigates to an item from page index > 1, Angular raises an ExpressionChangedAfterItHasBeenChecked
error. My code does not hold any change to a value which could be used anywhere higher in the component tree. So I guess it's a matter of interaction between the mat-table
and the mat-paginator
.
I created a very simple stackblitz project reproducing this behavior, hope someone can find how to work around this error. Note that when you click on item11
or item22
(first page), you can come back to list without raising the error. Whenever you click on item33
(second page), item55
or item66
(third page), the console does show the error when navigating back to the list.
Compiled with latest angular 8 libraries (core 8.2.14 and material 8.2.3).
Any help would be appreciated.
Upvotes: 1
Views: 1460
Reputation: 725
For completeness, I'm adding here the answer I got on this Material repo issue :
The trick is to restore the page index within a setTimeout
call :
ngAfterViewInit() {
if (this.itemsDS.paginator && this.itemsService.currentIndex > -1) {
setTimeout(() => {
this.itemsDS.paginator.pageIndex = this.itemsService.currentIndex;
this.itemsDS.paginator.page.emit({
length: this.itemsDS.paginator.getNumberOfPages(),
pageIndex: this.itemsService.currentIndex,
pageSize: this.itemsDS.paginator.pageSize
});
});
}
}
Hopefully this will be corrected within Angular Material one day. Have a look at this issue (which is already several years old).
Upvotes: 2