Search code examples
angularangular-materialpaginator

paginator is not reading data in angular


I am trying to implement a paginator with table in angular material. The data source comes from a Node.js server and works fine. However the paginator is like not reading the data table. I am not getting any error, but it is simply not working. Really appreciate your answers.

The Template -

<h3>Lista casos</h3>
<table mat-table [dataSource]="listaCasos" class="mat-elevation-z8">

    <ng-container matColumnDef="idcaso">
      <th mat-header-cell *matHeaderCellDef> ID Caso </th>
      <td mat-cell *matCellDef="let caso"> {{caso.ID_CASO}} </td>
    </ng-container>  

    <ng-container matColumnDef="estado">
      <th mat-header-cell *matHeaderCellDef> Estado </th>
      <td mat-cell *matCellDef="let caso"> {{caso.ESTADO_CASO}} </td>

    </ng-container>  

    <ng-container matColumnDef="causa">
        <th mat-header-cell *matHeaderCellDef> Causa </th>
        <td mat-cell *matCellDef="let caso"> {{caso.CAUSA}} </td>
    </ng-container> 

    <ng-container matColumnDef="detalles">
      <th mat-header-cell *matHeaderCellDef> Detalles </th>
      <td mat-cell *matCellDef="let caso"> 
        <a routerLink="/dashboard/gestion/{{caso.ID_CASO}}"><button mat-button>Ver caso</button></a>
      </td>
    </ng-container> 


    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table> 
<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>

The Component -

import { Component, OnInit } from '@angular/core';
import { CasosService } from './casos.service';
import { interCaso } from '../../interfaces/interCaso';
import {AfterViewInit, ViewChild} from '@angular/core';
import {MatPaginator} from '@angular/material/paginator';
import {MatTableDataSource} from '@angular/material/table';

@Component({
  selector: 'app-casos',
  templateUrl: './casos.component.html',
  styleUrls: ['./casos.component.css']
})
export class CasosComponent implements OnInit , AfterViewInit{

  listaCasos: interCaso[] = [];
  displayedColumns: string[] = ['idcaso' , 'causa' , 'estado' , 'detalles'];
  dataSource = new MatTableDataSource<interCaso>(this.listaCasos);

  constructor(private casosService: CasosService) { }

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

  @ViewChild(MatPaginator) paginator: MatPaginator;
  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
  }

  
  getCasos(){
    this.casosService.getCasos()
      .subscribe((casos : interCaso[]) => {        
        this.listaCasos = casos;
        console.log(casos);
      })
  }

}

Solution

    1. In the html, you are binding dataSource to listaCasos. This will cause the table to always remain filled up will all data, because the paginator doesn't respond to the listaCasos property, it responds to the dataSource property. Therefore, the binding should be to the dataSource property -
    <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
    
    1. In the component, you are initializing the dataSource with listaCasos on declaration. But, listaCasos will not be populated with data until ngOnInit() gets called. So, do not initialize the dataSource on declaration. Instead populate it inside the ngAfterViewInit() method -
    // leave the dataSource uninitialized
    dataSource = new MatTableDataSource<interCaso>();
    
    //populate dataSource here
    ngAfterViewInit() {
        this.dataSource.data = this.listaCasos;
        this.dataSource.paginator = this.paginator;
    }
    

    Edit :
    Sorry I tested with static data. But, in your case the casosService is fetching data asynchronously, and there is a chance of ngAfterViewInit() being called while the data has not arrived yet. Therefore, it would be better if you populate the data inside the subscription to the service call -

    // populate dataSource here
    getCasos(){
        this.casosService.getCasos()
          .subscribe((casos : interCaso[]) => {        
            //this.listaCasos = casos;
            this.dataSource.data = casos;
            console.log(casos);
          })
    }
    

    You'll not be needing listaCasos anymore.