Tips for retaining mat table paginator on the chosen page even after refreshing the page

Utilizing a mat table to display paginated data fetched from my API presents a challenge when the page is refreshed after the user navigates away. Instead of displaying the initial first page, I aim to show the second page.

To achieve this, I store the pageIndex in local storage and retrieve it upon refresh. While my API successfully fetches the second page, the pagination options appear incorrect:

Mat Page Options After Refresh

The displayed range shows 1-8 instead of 9-15, with navigation incorrectly set to the last page.

Below is the snippet of my HTML code:

<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>

And here are snippets of the TypeScript file:

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

Attempting a solution, I made the following changes:

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 seeking guidance on how to properly adjust the page range label and next/previous buttons.

Answer №1

It seems that the issue here lies in the synchronization between the paginator and the current page index along with the page size.

To resolve this problem, you will need to make some adjustments to your code:

For instance:

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';  // Customize this import according to your 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];  // Specify your preferred page size options
  page = {
    pageIndex: 0,
    pageSize: 8
  };
  totalItems = 15;  // Total count of items in your dataset

  constructor(private apiService: ApiService) {  // Inject your specific API service
    // Fetch 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 {
    // Retrieve 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 {
    // Implement your API call here to fetch data based on pageIndex and pageSize
    this.apiService.getData(pageIndex, pageSize).subscribe(data => {
      this.dataSource.data = data.items;
      
      // Update paginator length along with 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;

    // Store the current page index and size into localStorage
    localStorage.setItem('currentPageIndex', this.page.pageIndex.toString());
    localStorage.setItem('currentPageSize', this.page.pageSize.toString());

    // Retrieve fresh data based on the existing page index and size
    this.fetchData(this.page.pageIndex, this.page.pageSize);
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Extract a selection from a dropdown menu in ReactJS

I have multiple cards displayed on my screen, each showing either "Popular", "Latest", or "Old". These values are retrieved from the backend. I have successfully implemented a filter option to sort these cards based on popularity, age, etc. However, I am u ...

Showing the child component as undefined in the view

Within my Angular application, I encountered an issue involving a parent component named DepotSelectionComponent and its child component SiteDetailsComponent. The problem arises when an event called moreDetails is emitted to the parent component, triggerin ...

Utilizing TypeScript to define and implement interfaces and declarations for powerful customization

As you navigate through the collections typings file, a common pattern emerges: interface Set<T> { add(value: T): this; clear(): void; delete(value: T): boolean; forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void ...

Utilizing Typescript to pass props to a material-ui button enclosed in styled-components

After setting up my react project using the typescript template, I decided to style the material-ui Button component using the 'styled' method from the styled-components library as shown below: import React from 'react'; import styled f ...

Is there a way to order the execution of two functions that each produce promises?

With my code, I first check the status of word.statusId to see if it's dirty. If it is, I update the word and then proceed to update wordForms. If it's clean, I simply update wordForms. I'm looking for advice on whether this is the correct a ...

Generating dynamic rows and columns with Angular and Bootstrap in real time

I am looking to dynamically generate rows in an angular template, with each row containing 4 columns. For example, if the input is 40, the output should have 10 rows, each consisting of 4 columns. I am using bootstrap for my template layout. Below is what ...

In Typescript, inheritance of classes with differing constructor signatures is not permitted

While working on implementing a commandBus, I encountered an issue when trying to register command types with command handlers for mapping incoming commands. My approach was to use register(handler : typeof Handler, command : typeof Command), but it result ...

Disabling eslint does not prevent errors from occurring for the unicorn/filename-case rule

I have a file called payment-shipping.tsx and eslint is throwing an error Filename is not in camel case. Rename it to 'paymentShipping.tsx' unicorn/filename-case However, the file needs to be in kebab case since it's a next.js page that s ...

Error: Class cannot be loaded by React Webpack loader

I'm encountering an issue with my two typescript packages - a React application and an infrastructure package. The React app has a dependency on the infrastructure package (currently linked via npm). After adding a new class to the infrastructure pack ...

Generate a Jest dummy for testing an IncomingMessage object

I am facing a challenge in writing a unit test for a function that requires an IncomingMessage as one of its parameters. I understand that it is a stream, but I am struggling to create a basic test dummy because the stream causes my tests to timeout. : T ...

Angular, Transforming JSON with RxJS Operators in TypeScript

Upon receiving the JSON object (Survey) from the server, it looked like this: { "id": 870, "title": "test survey", "questions": [ { "id": 871, "data": ...

Invoking method in Angular component upon receiving a notification via ActionCable

Currently, I am practicing the utilization of ActionCable within Angular. To begin, I set up a rapid Rails application on Heroku, followed by creating an Angular application with the actioncable npm module integrated as a dependency. For experimentation p ...

Expanding the capabilities of i18next's translation function

I'm having trouble properly extending the function. I am stuck with the error Cannot redeclare block-scoped variable t. I am unsure if declaring a module is the correct approach (I am new to TypeScript). I have also tried creating a wrapper for the t ...

What is the best way to divide an HTML table into two sections?

I'm looking to organize my data into a table with two separate sections, one on the left and one on the right. For example, if I have 20 rows of data, I want to display the first 10 rows on the left side with headers and the remaining 10 rows on the r ...

Conditional void parameter type in Typescript

Attempting to create a custom Error class that can handle different data based on the error code seemed like a complex task for TypeScript. However, surprisingly, it was successful: const enum ERROR_CODES { E_AUTHORIZATION = 'Authorization error&ap ...

"Displaying the Material Input TextBox in a striking red color when an error occurs during

After referring to the links provided below, I successfully changed the color of a textbox to a darkish grey. Link 1 Link 2 ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline { color: #757575!important; } Although this solved the ...

Tips for safely storing JWT in the browser

I am currently working with Angular 10 on the front-end and obtaining a JWT from backend services. I am seeking the best method to securely store my Okta JWT in the browser while also mitigating the risk of XSS and XSRF attacks. I have looked into storing ...

Preparing JSON data for use with chart.js leveraging Angular 4 observables

Struggling to make sense of this dilemma, I find myself unable to crack the code. The data retrieved from my API is structured in the following format: "data": [ { "sr_count": 91, "month_name": "October", "month_num": 10, ...

Ensuring Consistency of Values Between Child and Parent Components

Is there a way to ensure that the value of submitted in the child component always matches the value of submitted in the parent component? Appreciate any help! @Component({ selector: 'child-cmp', template: ` child:{{submitted}} ...

Include a hash in the URL when the current location is entered into the view by scrolling

In my current situation, I am required to implement a @HostListener in order to navigate to an element within my web page: @HostListener('click', ['$event']) onClick(e: any) { e.preventDefault(); const href = e.target.getAttri ...