angulartypescriptangular-materialangular-material-tablemat-pagination

How to keep mat table paginator at selected page after refresh?


I am using mat table to show data and my API gives page-wise data. Now, first time it renders and then user changes the page and refreshes the page after, then I want to show the second page and not the first one.

To do that I have saved the pageIndex to local storage and retrieve it when the page refreshes and my API also calls the second page, but the pagination options are wrong as:

Mat Page Options After refesh

Which is showing 1-8; instead it should show 9-15 and also navigation is wrong as it is last page.

Here is my HTML

<mat-paginator
      class="mat-paginator-sticky"
      [hidden]="pageLength <= pageSizeOptions[0]"
      [pageSizeOptions]="pageSizeOptions"
      [showFirstLastButtons]="true"
      [length]="pageLength"
      [pageIndex]="page.pageIndex"
      (page)="pageChange($event)"
      aria-label="Select page of users"
    ></mat-paginator>

Here is ts file code snippets

constructor() {
     // Retrieve and set the current page index
     const savedPageIndex = localStorage.getItem('currentPageIndex');
     if (savedPageIndex) {
       this.page.pageIndex = +savedPageIndex;
       
     }
  }

I tried changes as

ngAfterViewInit(): void {
    setTimeout(() => {
      if (this.dataSource) {
        this.dataSource.sort = this.sort;
          this.paginator.pageIndex = this.page.pageIndex;
          this.paginator.pageSize = this.page.pageSize;
          this.paginator.length = this.pageLength;
          this.paginator._changePageSize(this.paginator.pageSize);
          this.dataSource.paginator = this.paginator;
         
      }
    });
  }

I am expecting a way to change or correct the page range label and next prev buttons.


Solution

  • I think what we have here is a case of the paginator not correctly synchronized with the current page index and page size.

    You will need to modify your code a bit:

    for example:

    import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
    import { MatPaginator } from '@angular/material/paginator';
    import { MatTableDataSource } from '@angular/material/table';
    import { ApiService } from './api.service';  // Adjust this import to your actual API service
    
    @Component({
      selector: 'app-your-component',
      templateUrl: './your-component.component.html',
      styleUrls: ['./your-component.component.css']
    })
    export class YourComponent implements OnInit, AfterViewInit {
      @ViewChild(MatPaginator) paginator!: MatPaginator;
      dataSource = new MatTableDataSource<any>([]);
      pageSizeOptions = [8, 16, 24];  // Your page size options
      page = {
        pageIndex: 0,
        pageSize: 8
      };
      totalItems = 15;  // Total number of items in your data set
    
      constructor(private apiService: ApiService) {  // Inject your API service
        // Retrieve and set the current page index and page size
        const savedPageIndex = localStorage.getItem('currentPageIndex');
        const savedPageSize = localStorage.getItem('currentPageSize');
        if (savedPageIndex) {
          this.page.pageIndex = +savedPageIndex;
        }
        if (savedPageSize) {
          this.page.pageSize = +savedPageSize;
        }
      }
    
      ngOnInit(): void {
        // Fetch initial data
        this.fetchData(this.page.pageIndex, this.page.pageSize);
      }
    
      ngAfterViewInit(): void {
        let isPaginatorInitialized = false;
        while (!isPaginatorInitialized) {
          if (this.paginator) {
            this.paginator.pageIndex = this.page.pageIndex;
            this.paginator.pageSize = this.page.pageSize;
            this.paginator.length = this.totalItems;
            this.dataSource.paginator = this.paginator;
            isPaginatorInitialized = true;
          }
        }
    
        this.paginator.page.subscribe(event => {
          this.pageChange(event);
        });
      }
    
      fetchData(pageIndex: number, pageSize: number): void {
        // Call your API here to fetch data based on pageIndex and pageSize
        this.apiService.getData(pageIndex, pageSize).subscribe(data => {
          this.dataSource.data = data.items;
          
          // Update paginator length and pageIndex
          this.paginator.length = this.totalItems;
          this.paginator.pageIndex = pageIndex;
          this.paginator.pageSize = pageSize;
        });
      }
    
      pageChange(event: any): void {
        this.page.pageIndex = event.pageIndex;
        this.page.pageSize = event.pageSize;
    
        // Save the current page index and size to localStorage
        localStorage.setItem('currentPageIndex', this.page.pageIndex.toString());
        localStorage.setItem('currentPageSize', this.page.pageSize.toString());
    
        // Fetch new data based on the current page index and size
        this.fetchData(this.page.pageIndex, this.page.pageSize);
      }
    }