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