How can we efficiently load paginated data from a database while still implementing pagination using Angular Material?

I have a large table with more than 1000 entries that I want to display using a

<mat-table></mat-table>
.

Since loading all the entries at once would be too much, I am looking to implement pagination and load only 20 entries per page.

The challenge is that according to the documentation for the "Paginator," it requires all entries to be loaded when initialized.

Each instance of the paginator needs: The number of items per page (default is set to 50) & The total number of items being paginated

https://material.angular.io/components/paginator/overview

Is there a workaround to still use the Angular Material Paginator without having to provide all entries upfront?

Thank you for any assistance!

Answer №1

Check out this documentation for the Angular Material Paginator API

After reviewing the provided documentation, it is evident that the paginator emits a page event each time the page changes.

Initially, when loading data, only the rows from the first page are fetched from the server, causing the next page to be inaccessible. To address this, in addition to the current row set, populate the total number of available rows and assign it as the length before setting the data to the datasource. This approach allows the mat paginator to function as though it has all data stored.

In simpler terms, using obj.length = response.total will fill in null values for any missing data entries.

During each page event occurrence, another API call is made to retrieve and insert the necessary data at the specified index, size, and previous index points.

For further clarity, here is an example reference code:

app.component.ts

import { Component, ViewChild } from '@angular/core';

import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { HttpClient, HttpParams } from '@angular/common/http';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  users: any[];
  loading: boolean = true;
  dataSource = new MatTableDataSource<any>();

  title = 'pagination';

  @ViewChild(MatPaginator) paginator: MatPaginator;

  constructor(private http: HttpClient) {

  }

  ngOnInit() {
    this.getData('0', '5');
  }

  getData(offset, limit){
    let params = new HttpParams();
    params = params.set('offset', offset);
    params = params.set('limit', limit);

    this.http.get('http://localhost:3000/users?' + params.toString())
    .subscribe((response: any) =>{

      this.loading = false;
      this.users = response.users;
      this.users.length = response.total;

      this.dataSource = new MatTableDataSource<any>(this.users);
      this.dataSource.paginator = this.paginator;

    })
  }

  getNextData(currentSize, offset, limit){
    let params = new HttpParams();
    params = params.set('offset', offset);
    params = params.set('limit', limit);

    this.http.get('http://localhost:3000/users?' + params.toString())
    .subscribe((response: any) =>{

      this.loading = false;

      this.users.length = currentSize;
      this.users.push(...response.users);

      this.users.length = response.total;

      this.dataSource = new MatTableDataSource<any>(this.users);
      this.dataSource._updateChangeSubscription();

      this.dataSource.paginator = this.paginator;
  
    })
  }

  pageChanged(event){
    this.loading = true;

    let pageIndex = event.pageIndex;
    let pageSize = event.pageSize;

    let previousIndex = event.previousPageIndex;

    let previousSize = pageSize * pageIndex;

    this.getNextData(previousSize, (pageIndex).toString(), pageSize.toString());
  }
}

The method getNextData(currentSize, offset, limit) contains the key logic. By ensuring the length is initially set to the total count, adding additional data beyond the initial index may lead to null values within the dataset. To address this, reset the size back to the current count after inserting data, adjusting its size to match the total count.

For more insights, refer to: Server-Side Pagination with Angular Material Data Table Paginator

Repository Link on Github: Github Repository - Server Side Pagination Mat Paginator

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

Angular sets the required property only when the button is clicked

Is there a way to make a field required in Angular only when a button is clicked? Currently, the error message appears even before the user interacts with the field. I would like the error message "folder name is required" to only appear when the user cli ...

What causes the string to be treated as an object in React Native?

I am fetching a string value through an API and I need to display it in the View. However, the string value is coming as a Promise. How can I handle this? "Invariant Violation: Objects are not valid as a React child (found: object with keys {_40, _65 ...

Is the "ngIf" directive not functioning properly within a "ngFor" loop in Angular?

I am in the process of developing an e-commerce website that focuses on selling a variety of shirts. Currently, I have set up a system where all the available shirts are displayed using an *ngFor loop. My goal is to create a feature that allows users to cl ...

Making a REST API call with an ID parameter using Angular

I am currently working on an Angular application that interacts with a REST API. The data fetched from the API is determined based on the customer ID, for example: api/incident?customer_id=7. I am unsure of how to incorporate this into the API URL and serv ...

Angular form input set to disabled mode

Visit this link for code <form class="example-form"> <mat-form-field class="example-full-width"gt; <mat-label></mat-label> <input matInput placeholder="Ex. Pizza" [disabled]="filterVal ...

Angular with Firebase: How to ignore a field in a query

I am curious to see if my current structure is compatible with Firebase, or if I need to make adjustments. Let's take a look at an example using the "/rooms" endpoint, which contains an array of Room objects: export class Room { id: number; p ...

Modifying the value of a React input component is restricted when the "value" field is utilized

I'm currently utilizing material-UI in my React application. I am facing a challenge where I need to remove the value in an input field by clicking on another component. The issue arises when using the OutlinedInput component with a specified value. ...

An error has occurred: (SystemJS) A request error (404 Not Found) occurred while trying to load ng2-gridstack

I'm having some trouble installing the ng2-gridstack module on my Angular2 application. After a fresh installation, I ran: npm install gridstack (dependency) npm install ng2-gridstack I've been following the instructions, but unfortunately, I e ...

Displaying individual information for each Bootstrap modal in Angular can be achieved by properly binding the data

While looping through images, a modal pops up with its information when clicked. The issue is that all the modals associated with different images display the same content as the first image. This is what has been attempted: data:any; HTML <div *ngFo ...

Generating TypeScript declarations for legacy CommonJS dependencies with the correct "module" setting

One of my challenges involves creating type declarations for outdated dependencies that produce CJS modules and lack typings. An example is the aabb-3d module (although this issue isn't specific to that particular module). To generate the declaration ...

Understanding how types intersect in TypeScript

I'm currently diving into Type Relations in TypeScript. Can someone help explain what happens when we intersect the types represented by these two expressions: {a:number}[] & {b:string}[] Does this result in {a:number, b:string}[] ? Any clarificat ...

The best practices for utilizing ES6 Modules syntax in TypeScript files within a NextJS environment

The issue appears to be trapped in a loop: package.json is missing type: "module". This results in an error when trying to use modules in TypeScript files: An error occurred while running the seed command: /Users/me/code/me/prisma-learning/grap ...

Typescript interface created specifically for React Higher Order Component Props

Consider the React HOC provided below which adds sorting state to a component: import React, {Component, ComponentClass, ComponentType} from 'react' interface WithSortState { sortOrder: string } interface WithSortInjectedProps { sortO ...

Encounter a Typescript error when dealing with "app.ws" while using express-ws

I have a small project in mind where I want to create a BabyCam that can be accessed from any web browser using a Raspberry Pi Zero. My plan is to set up a web socket using express-is to stream video to multiple clients. I'm utilizing the raspivid-str ...

The JSX element 'SubscribeCard' does not contain any construct or call signatures

I'm looking to implement the react-subscribe-card module for handling email subscriptions in my react.js project. Below is the code snippet from my popup.tsx file: import React from "react"; import SubscribeCard from "react-subscribe-c ...

how can one exhibit the value of an object in TypeScript

Does anyone know how to properly display object values in forms using Angular? I can see the object and its values fine in the browser developer tools, but I'm having trouble populating the form with these values. In my *.ts file: console.log(this.pr ...

Combine Immer and NgRx reducer for improved state management

Upon analyzing redux and ngrx, it appears that immer is the preferred library for creating a copy of the state before storing it. In following the example provided by immer, I implemented the following code in my reducer: on(exampleActions.updateExample ...

How to retrieve the value of a variable accessible to all users in Angular?

In my code, I am working with a service variable called Users. Service: Users:BehaviorSubject<Array<any>> = new BehaviorSubject([]); I am updating the values in the component using this code: this.Service.Users.next([...this.Service.User ...

Is there a way to include the present date and time within a mat-form-field component in Angular?

I'm working on a mat-form-field to display the current time inside an input field. I've managed to insert it, but I'm struggling with the styling. Here's the snippet of code I'm using: <mat-label>Filing Time:</mat-label> ...

Angular 2 - Constructing dates in constructor - Error: Type 'Date' cannot be assigned to type 'string'

In my attempt to generate a fresh date object for an ngx-chart by referencing this specific example, I came across the following code snippet: constructor() { this.data = this.multi.map(group => { group.series = group.series.map(dataItem =& ...