angulartypescriptangular-materialangular-material-tablemat-pagination

Angular Mat Pagination and Mat Sort are not working


enter image description here

Mat Pagination (shows 0 of 0) and Mat Sort are not working. Can someone help? I tried other solutions available on the Stack Overflow but that does not seem to work for me.

Sample data from API:

{
    "body": {
    "httpstatuscode": 200,
    "AppData": [
        {
            "disk": "0",
            "load": "0.25",
            "sno": 1,
            "instances": "Instance1",
            "cpu": "0",
            "ram": "0.25"
        },
        {
            "disk": "0",
            "load": "0",
            "sno": 2,
            "instances": "Instance2",
            "cpu": "0",
            "ram": "0"
        }
    ],
    "opStatusCode": 2000,
    "type": "SUCCESS",
    "message": "DATA RECEIVED SUCCESSFULLY"
}

Here is my component.html code:

<div>  
  <table style="position: sticky; overflow: scroll;"
    mat-table
    matSort
    [dataSource]="dataSource">
    <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->

    <ng-container matColumnDef="sno">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>SNO</th>
      <td mat-cell *matCellDef="let element">{{ element.sno }}</td>
    </ng-container>

    <ng-container matColumnDef="instances">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Instances</th>
      <td mat-cell *matCellDef="let element">{{ element.instances }}</td>
    </ng-container>

    <ng-container matColumnDef="cpu">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>CPU %</th>
      <td mat-cell *matCellDef="let element">{{ element.cpu }}</td>
    </ng-container>

    <ng-container matColumnDef="ram">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>RAM %</th>
      <td mat-cell *matCellDef="let element">{{ element.ram }}</td>
    </ng-container>

    <ng-container matColumnDef="load">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Load %</th>
      <td mat-cell *matCellDef="let element">{{ element.load }}</td>
    </ng-container>

    <ng-container matColumnDef="disk">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Disk %</th>
      <td mat-cell *matCellDef="let element">{{ element.disk }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
    <!-- <tr
      mat-row
      class="remove-background"
      (mouseover)="onMouseOver(e)"
      *matRowDef="let row; let e = index; columns: displayedColumns"
      [ngClass]="{ 'mat-elevation-z8': e == mouseOverIndex, 'background-color': blue }"
    ></tr> -->
    <tr (click)="fetchProxyData(row.instances)" mat-row *matRowDef="let row; let e = index; columns: displayedColumns;"></tr>

    <!-- Row shown when there is no matching data. -->
    <tr class="mat-row" *matNoDataRow>
      <td class="mat-cell" colspan="4">
        <!-- No data matching the filter "{{ input.value }}" -->
        Data not available.
      </td>
    </tr>
  </table>

  <mat-paginator  #paginator
    [pageSizeOptions]="[5, 10, 25, 100, 150, 200]"
    aria-label="Select page of users" class="mat-paginator-sticky"
  ></mat-paginator>
</div>

This is the component.ts file. Sharing only some parts of it because containing some sensitive details.

export interface tableData {
  sno: number;
  instances: string;
  cpu: number;
  ram: number;
  load: number;
  disk: number;
}

dataForTable: tableData[] = []; 
cpuData=[]; 
ramData=[]; 
loadData=[]; 
diskData=[];

displayedColumns: string[] = ['sno', 'instances', 'cpu', 'ram', 'load', 'disk'];
dataSource = new MatTableDataSource(this.dataForTable);

@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;

constructor(private httpclient: HttpClient, private httpService: HttpService) {}

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

ngOnInit(): void { 
  this.fetchData(); 
}

fetchData() {

  this.httpService.getData(request).subscribe((response: any) => {
    const responseString: string = JSON.stringify(response);
    try {
      const jsonObj = JSON.parse(responseString);
      const jsonBody = jsonObj['body'];
      const appData = jsonBody['AppData'];
      this.dataForTable = appData as tableData[];
      this.dataSource=new MatTableDataSource(this.dataForTable);
    } catch (e: any) {
      console.log('Error in parsing json ' + e.message);
    }
    return response;
  });
}

Solution

  • Assign MatPaginator and MatSort instances to MatTableDataSource after the data is provided.

    fetchData() {
      this.httpService.getData(request).subscribe((response: any) => {
    
        try {
          const jsonBody = response['body'];
          const appData = jsonBody['AppData'];
          this.dataForTable = appData as tableData[];
          this.dataSource = new MatTableDataSource(this.dataForTable);
    
          this.dataSource.paginator = this.paginator;
          this.dataSource.sort = this.sort;
        } catch (e: any) {
          console.log('Error in parsing json ' + e.message);
        }
    });
    

    Demo @ StackBlitz

    Side note: You can access the body field from the response. Stringify the (JSON) object and convert the string back to JSON is unnecessary.

    const jsonBody = response['body'];