Iwaneez
Iwaneez

Reputation: 87

Material pagination does not work when inside *ngIf

I have this code with pagination inside, but the pagination does not work. It always shows all elements. But removing *ngIf from container div, it just woks. Why it is so? How to make it work with *ngIf? I really need to use it.

<div *ngIf="savingTransactionsDataSource" class="mat-elevation-z8">

    <table mat-table [dataSource]="savingTransactionsDataSource">
        <ng-container [matColumnDef]="column" *ngFor="let column of items">
          ...
        </ng-container>
        <tr mat-header-row *matHeaderRowDef="savingColumnsToDisplay; sticky: true;"></tr>
        <tr mat-row *matRowDef="let row; columns: savingColumnsToDisplay;"></tr>
    </table>

    <mat-toolbar class="mat-toolbar-sticky">
        <mat-toolbar-row>

            <span class="spacer"></span>

            <mat-paginator [length]="savingTransactionsDataSource.data.length"
                           [pageSize]="5"
                           [pageSizeOptions]="[5, 10, 15, 20]"
                           showFirstLastButtons>
            </mat-paginator>

        </mat-toolbar-row>
    </mat-toolbar>
</div>

Upvotes: 2

Views: 2258

Answers (2)

Kaleb Dalla Pria
Kaleb Dalla Pria

Reputation: 69

I had the same problem because I was using the async pipe in my template and after some research I was able to make it work using the @ViewChild annotation and a set function.

The hidden solution didn't work for me.

In my component.ts file:

  constructor(private cdRef: ChangeDetectorRef) { }

  private paginator: MatPaginator;
  /*
   We are using @ViewChild because of the ngIf with async pipe on the template
   When the data is emmited for the first time from the observable, we need to bind the
   pagination component with the datasource. This can be achieved with the code bellow.
  */
  @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
    if(mp) {
      this.paginator = mp;
      this.dataSource = new MatTableDataSource<any>(your_data);
      this.dataSource.paginator = this.paginator;
      this.cdRef.detectChanges();
     }
   }

and in my template file:

  // my observable with the async pipe
  <div *ngIf="raceList$ | async as races">
    <div class="mat-table-width">
      <table mat-table [dataSource]="dataSource">
      ...
      </table>
      <mat-paginator [pageSizeOptions]="[10, 20, 30]"
                      showFirstLastButtons
                      aria-label="select page of races">
      </mat-paginator>
    </div>
  </div>

Upvotes: 1

rvrsev
rvrsev

Reputation: 176

According to this GitHub issue, the paginator breaks inside an ngIf, but you can try to use this snippet to get around the problem:

@ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
    this.paginator = mp;
    this.setDataSourceAttributes();
  }

  setDataSourceAttributes() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

Alternatively, another solution posted was to use the hidden attribute instead of ngIf.

<div [hidden]="isLoading">
  <mat-table [dataSource]="dataSource">
  ...
  </mat-table>
</div>

Upvotes: 4

Related Questions