Angular Material Table Pagination Not Working

789 Views Asked by At

I am working on a angular application which will get the data with HTTP GET API call and load the same in a table. For data state management I am using NgRx. The data is loading fine in the table and I am able to load the same with angular material table. But the material pagination is not working properly.

I have tried multiple steps to resolve this issue like,

  • adding the paginator using @ViewChild,
  • in @ViewChild check if the dataSource is not undefine
  • With the ChangeDetectorRef to detect changes after setting dataSource

But still it is not working as expected.

Any help will be highly appreciated.

home.component.ts

import {
  AfterViewInit,
  ChangeDetectorRef,
  Component,
  OnChanges,
  OnInit,
  SimpleChanges,
  ViewChild,
} from '@angular/core';
import { Store } from '@ngrx/store';
import { Coffee } from '../models/coffee.model';
import { getCoffee } from '../store/actions/coffee.action';
import { CoffeState } from '../store/reducers/coffee.reducer';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { flatMap, Subject, takeUntil } from 'rxjs';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  coffees: Coffee[] = [];
  coffeeData$: any;
  displayedColumns = [
    'id',
    'uid',
    'blend_name',
    'origin',
    'variety',
    'notes',
    'intensifier',
  ];
  dataSource!: MatTableDataSource<Coffee>;
  //paginator!: MatPaginator;

  //@ViewChild(MatPaginator, { static: false }) paginator!: MatPaginator;

  @ViewChild(MatPaginator, { static: false })
  set paginator(value: MatPaginator) {
    if (this.dataSource) {
      this.dataSource.paginator = value;
    }
  }

  constructor(
    private store: Store<CoffeState>,
    private cdr: ChangeDetectorRef
  ) {}
  ngOnInit(): void {
    this.getAllCoffees();
    //this.coffeeData$ = this.store.select(`coffees`);
    this.coffeeData$ = this.store.select((store) => store.coffees);
    console.log('this.coffeeData$ ', this.coffeeData$);

    this.dataSource = this.coffeeData$;
    this.cdr.detectChanges();
  }

  getAllCoffees() {
    this.store.dispatch(getCoffee());
  }
}

home.component.html

<div class="container">
  <div class="example-header">
    <h2 class="header-text">Coffee App</h2>
  </div>
  <div class="example-container mat-elevation-z8">
    <mat-paginator
      [pageSizeOptions]="[10, 25, 50]"
      aria-label="Select page of coffees"
    ></mat-paginator>
    <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
      <!--- Note that these columns can be defined in any order.
            The actual rendered columns are set as a property on the row definition" -->

      <!-- ID Column -->
      <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef>No</th>
        <td mat-cell *matCellDef="let element">{{ element.id }}</td>
      </ng-container>
      <ng-container matColumnDef="uid">
        <th mat-header-cell *matHeaderCellDef>User Id</th>
        <td mat-cell *matCellDef="let element">{{ element.uid }}</td>
      </ng-container>
      <ng-container matColumnDef="blend_name">
        <th mat-header-cell *matHeaderCellDef>Blend Name</th>
        <td mat-cell *matCellDef="let element">{{ element.blend_name }}</td>
      </ng-container>
      <ng-container matColumnDef="origin">
        <th mat-header-cell *matHeaderCellDef>Origin</th>
        <td mat-cell *matCellDef="let element">{{ element.origin }}</td>
      </ng-container>
      <ng-container matColumnDef="variety">
        <th mat-header-cell *matHeaderCellDef>Variety</th>
        <td mat-cell *matCellDef="let element">{{ element.variety }}</td>
      </ng-container>
      <ng-container matColumnDef="notes">
        <th mat-header-cell *matHeaderCellDef>Notes</th>
        <td mat-cell *matCellDef="let element">{{ element.notes }}</td>
      </ng-container>
      <ng-container matColumnDef="intensifier">
        <th mat-header-cell *matHeaderCellDef>Intensifier</th>
        <td mat-cell *matCellDef="let element">{{ element.intensifier }}</td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
    </table>
  </div>
</div>
1

There are 1 best solutions below

0
On

this.dataSource needs to be an instance of MatTableDataSource, I would suggest to re-wite the onInit logic like this

ngOnInit(): void {
  this.getAllCoffees();
  this.coffeeData$ = this.store.select((store) => store.coffees).subscribe(
    (data: Coffee[]) => this.dataSource = new MatTableDataSource(data)
  );
}