Skip to content


Switch branches/tags

Latest commit

Bumps []( from 6.1.0 to 6.1.2.
- [Release notes](
- [Changelog](
- [Commits](socketio/

- dependency-name:
  dependency-type: indirect

Signed-off-by: dependabot[bot] <>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]>

Git stats


Failed to load latest commit information.
Latest commit message
Commit time

npm-badge   travis-badge   codecov-badge

ngx-pagination-data-source provides an easy to use paginated DataSource for Angular Material & CDK that works with HTTP or any other way you're fetching pages. Configure a model for querying the data and hook up any inputs for searching, filtering and sorting - plus loading indication!

Example StackBlitz

🔍 In-Depth Explanation


npm i ngx-pagination-data-source


Have a type you want to display in a table (or any other component accepting a DataSource).

export interface User {
  id: number
  username: string
  email: string
  phone: string
  registrationDate: Date

Define a query model and a service that can fetch pages based on this model.

import { PageRequest, Page } from 'ngx-pagination-data-source'

export interface UserQuery {
  search: string
  registration: Date

@Injectable({providedIn: 'root'})
export class UserService {
  page(request: PageRequest<User>, query: UserQuery): Observable<Page<User>> {
    // transform request & query into something your server can understand
    // (you might want to refactor this into a utility function)
    const params = {
      pageSize: request.size,
      sortOrder: request.sort.order,
    // fetch page over HTTP
    return this.http.get<Page<User>>('/users', {params})
    // transform the response to the Page type with RxJS map() if necessary

Create the data source typed with the type you want to fetch and the corresponding query model. Pass a function pointing to your service and default values for the query and sort.

import { PaginationDataSource } from 'ngx-pagination-data-source'

export class UsersComponent  {
    displayedColumns = ['id', 'name', 'email', 'registration']

    dataSource = new PaginationDataSource<User, UserQuery>(
      (request, query) =>, query),
      {property: 'username', order: 'desc'},
      {search: '', registration: undefined}

    constructor(private users: UserService) { }

Hook the data source to a table and paginator in your view. Hook any query inputs to dataSource.queryBy() to provide a partial new query that will be merged with the existing one. You can also hook up inputs to dataSource.sortBy() in the same way.

You can optionally add loading indication by e.g. hooking up a spinner to dataSource.loading$.

  <mat-icon matPrefix>search</mat-icon>
  <input #in (input)="dataSource.queryBy({search: in.value})" type="text" matInput>
<mat-form-field class="registration">
  <input (dateChange)="dataSource.queryBy({registration: $event.value})" matInput 
    [matDatepicker]="picker" placeholder="Registration"/>
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
<mat-form-field class="property">
  <mat-label>Order by</mat-label>
  <mat-select value="username" (selectionChange)="dataSource.sortBy({property: $event.value})">
    <mat-option value="id">ID</mat-option>
    <mat-option value="username">Username</mat-option>
<mat-button-toggle-group value="asc" (change)="dataSource.sortBy({order: $event.value})">
  <mat-button-toggle value="asc"><mat-icon>arrow_upward</mat-icon></mat-button-toggle>
  <mat-button-toggle value="desc"><mat-icon>arrow_downward</mat-icon></mat-button-toggle>
<table mat-table [dataSource]="dataSource">
  <!-- column definitions -->
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<mat-paginator *ngIf="$ | async as page"
  [length]="page.totalElements" [pageSize]="page.size"
  [pageIndex]="page.number" (page)="dataSource.fetch($event.pageIndex)">
<mat-spinner *ngIf="dataSource.loading$ | async" diameter="32"></mat-spinner>