Initialising MatPaginator asynchronously

2019-08-21 18:05发布

问题:

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.

回答1:

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.



回答2:

I just had the same problem.This is a known problem and they have solved this, in my opinion, better.

 @ViewChild(MatPaginator) set matPaginator( paginator: MatPaginator){
   this.dataSource.paginator = paginator;
 }
 @ViewChild(MatSort) set matSort( sort: MatSort){
   this.dataSource.sort = sort;
 }

https://github.com/angular/material2/issues/10205#issuecomment-465455599