We initialise MatPaginator in our components
like
@ViewChild(MatPaginator) paginator: MatPaginator;
and assign to a MatTable DataSource
defined in our component as
matTableDataSource.paginator = this.paginator;
This doesn't work in a use case when the data source is initialised asynchronously using async
pipe with a combination of *ngIf
. As,
<div *ngIf="someDataObs | async as yourData else loading">
<mat-table #table [dataSource]="yourData">
... your headers and columns
</mat-table>
<mat-paginator [pageSize]="10" showFirstLastButtons></mat-paginator>
</div>
Note: you could put mat-paginator
below the div
with *ngIf
, but that's not an ideal solution, more so if you need to show multiple tables in a same component coming with a single backend asynchronous call.
Since the mat-paginator
will get initialised asynchronously, using a code such as below will not work as paginator
will be null
.
ngAfterViewInit() {
this.someDataObs = this.backendService.get()
.map(value => {
const matTableDataSource = new MatTableDataSource<SomeType>(value);
matTableDataSource.paginator = this.paginator; // will be null here
return matTableDataSource;
});
}
To have a way for this to work would've required MatPaginator
to have an output property
to emit once initialised, but that doesn't exist for now.
Use of async
pipe and *ngIf
makes the code really concise and you should not avoid it to overcome this use case.
Any solution to achieve this would be helpful.
Endeed, your problem is the *ngIf.
With
@ViewChild(MatPaginator) paginator: MatPaginator
, when paginator is requested, it is not found in the DOM and it return null.A solution to this problem, is to replace your *ngIf by a statement with
display:none
. So the paginator will stay in the DOM.I just had the same problem.This is a known problem and they have solved this, in my opinion, better.
https://github.com/angular/material2/issues/10205#issuecomment-465455599