'Angular Paginator not working after data reload

I am trying to share a Angular material table MAT-TABLE among different material tabs MAT-TABS. Also, i'm getting data from a API so i am calling a function on each tab click.

The data is being retrieved and inserted into the table, but the paginator and filter stopped working. The working code can be seen here,

https://stackblitz.com/edit/angular-aq9hja

Here's the sample of HTML,

    <mat-tab-group (selectedTabChange)="tabClick($event)"  >
        <mat-tab label="Type1">
            {{debug+1}}<br>
            <ng-container *ngTemplateOutlet="tabContent"></ng-container>
        </mat-tab>
        <mat-tab label="Type2">
            {{debug+1}}<br>
            <ng-container *ngTemplateOutlet="tabContent"></ng-container>
        </mat-tab>
    </mat-tab-group>

    <ng-template #tabContent>
        <mat-form-field>
            <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
        </mat-form-field>
        <div class="mat-elevation-z8">
            <table mat-table [dataSource]="getDatasource()" matSort>
                <ng-container matColumnDef="ID">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
                    <td mat-cell *matCellDef="let row"> {{row.ID}} </td>
                </ng-container>
                <ng-container matColumnDef="AUTHOR">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> AUTHOR </th>
                    <td mat-cell *matCellDef="let row"> {{row.AUTHOR }} </td>
                </ng-container>
                <ng-container matColumnDef="COUNT">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> TOTAL ARTS </th>
                    <td mat-cell *matCellDef="let row"> {{row.COUNT}} </td>
                </ng-container>
                <tr mat-header-row *matHeaderRowDef="getDisplayedColumns()"></tr>
                <tr mat-row *matRowDef="let row; columns: getDisplayedColumns();"
                    >
                </tr>
            </table>
            <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
        </div>
    </ng-template>

And here's the component.ts

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { MatTableDataSource } from '@angular/material/table';
    import { MatSort } from '@angular/material/sort';
    import { MatPaginator } from '@angular/material/paginator';
    import {MatTabsModule} from '@angular/material/tabs';
    import { HttpClient, HttpParams, HttpHeaders, HttpErrorResponse } from '@angular/common/http';

    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      name = 'Angular';


      constructor(private http: HttpClient) { }

      private dataSource: MatTableDataSource<any>;
      private displayedColumns: string[] = [];
      private isLoading: boolean = true;

      private debug:number=0;

      @ViewChild(MatSort, { static: true }) sort: MatSort;
      @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;

      ngOnInit() {
        console.log("NGINIT"+this.debug++);
        this.dataSource = new MatTableDataSource();
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
        this.populateType("", "1", "9999");
      }

      populateType(id: any, page: any, limit: any) {
        ...
      }

        populateForm(id: any, page: any, limit: any) {
        ...
      }

      applyFilter(filterValue: string) {
        this.dataSource.filter = filterValue.trim().toLowerCase();
        if (this.dataSource.paginator) {
          this.dataSource.paginator.firstPage();
        }
      }

      isPageLoading(): boolean {
        return this.isLoading;
      }
      getDatasource(): MatTableDataSource<any> {
        return this.dataSource;
      }
      getDisplayedColumns(): string[] {
        return this.displayedColumns;
      }
      tabClick(event: any) {
        console.log(event.index);
        switch (event.index) {
          case 0: 
          console.log("CASE1"+this.debug++);
          this.populateType('','1','999999');
          this.dataSource.paginator = this.paginator;
          this.dataSource.sort = this.sort;
          console.log('Type1');
            break;
          case 1: 
          console.log("CASE2"+this.debug++);
          this.populateForm('','1','999999');
          this.dataSource.paginator = this.paginator;
          this.dataSource.sort = this.sort;
          console.log('Type2');
            break;

        }
      }
    }

BUMP



Solution 1:[1]

A working https://stackblitz.com/edit/angular-yqdsr6 with the answer.

With multiple mat-paginator you'll have to use @ViewChildren instead of @ViewChild

I also had to tweak the imports in your app.module.ts

Solution 2:[2]

While you are using Angular 8 , @ViewChild is returning always an undefined, use in the template :

<mat-paginator #matPagi [pageSizeOptions]="[3, 5, 10, 25]"  ></mat-paginator>

and in the class AppComponent

  @ViewChild('matPagi', { static: true }) paginator: MatPaginator;

And don't forget to import hammer.js in your main.js or in polyfils.js becouse of Angular Material's dependencies

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 C_Ogoo
Solution 2 Youssef Tounoussi