Angular Material Table - Pagination, Sort, Filter
26 September 2019
In this post, you will learn how to add a data table using Angular Material. This data table is built on the foundation of the CDK data-table. We are going to cover how to add pagination, sort, filter. This is a step-by-step tutorial, so I invite you to code along. Here's the result of what this post will look like!

So, without any further delay, let's dive in
Prerequisites
As a dummy server for data, I will be using json-server npm package for an API call. API response contains an array of superheroes that will be displayed inside the table
I have created a new Angular CLI project and removed all the Html code that was inside app.html.ts and then added Angular material using ng add @angular/material command. Then I have added json-server npm package using npm i -D json-server command and added the following data in a db.json file inside root of this project
Now, When I run command json-server --watch db.json, it will act as a mock server so when I hit http://localhost:3000/heros, I'll get the heros array as API response. Isn't it cool?

{
"heros": [
{
"id": 1,
"name": "Iron Man",
"fullName": "Tony Stark",
"placeOfBirth": "New York",
"publisher": "Marvel Comics"
},
.....
{
"id": 10,
"name": "Wolverine",
"fullName": "Logan",
"placeOfBirth": "Canada",
"publisher": "Marvel Comics"
}
]
}
Now that our fake backend is ready, Let's add code to use this data inside the angular material table
Material table
An Angular material data table is a configurable component for displaying tabular data. The table will take the array as input and render a row for each object in the data array Let's start with displaying data in our table
let’s create a file app.interfaces.ts and add the following interface to it
export interface IHero {
id: number;
name: string;
fullName: string;
placeOfBirth: string;
publisher: string;
}
I am going to import MatFormFieldModule, MatInputModule, HttpClientModule, MatTableModule, MatPaginatorModule, MatSortModule, MatProgressSpinnerModule modules inside this app so for that I've added an entry of these modules inside the imports array of app.module.ts
Here's what every module contains
- MatFormFieldModule - This encompasses all the different types of form fields that Angular Material has available
- MatInputModule - This contains the components and directives for adding Material design Input Boxes to our application (needed for the search input box)
- HttpClientModule - This is the module is used to perform HTTP requests
- MatTableModule - This is the core data table module, which includes the mat-table component and many related components and directives
- MatPaginatorModule - This is a generic pagination module, that can be used to paginate data in general
- MatSortModule - This is an optional module that allows adding sortable headers to a data table
- MatProgressSpinnerModule - This module includes the progress indicator component that we will be using to indicate that data is being loaded from the backend
import {
MatTableModule, MatSortModule, MatFormFieldModule,
MatInputModule, MatPaginatorModule
} from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
.....
imports: [
...
BrowserAnimationsModule,
MatFormFieldModule,
MatInputModule,
HttpClientModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
],
Add the following code in your app.component.ts and app.html.ts
import { MatTableDataSource, MatSort, MatPaginator } from '@angular/material';
import { IHero } from './app.interfaces';
.....
displayedColumns = ['id', 'name', 'fullName', 'placeOfBirth', 'publisher'];
dataSource = new MatTableDataSource<IHero>();
constructor(
private httpClient: HttpClient
) { }
ngOnInit() {
this.httpClient.get('http://localhost:3000/heros')
.subscribe((heros: IHero[]) => {
this.dataSource.data = heros;
});
}
The mat-table's dataSource attribute, we have passed the dataSource attribute which is of type MatTableDataSource. Inside every ng-container tag, we define the column definition and the value to be displayed. It should be noted that we must match the matColumnDef value with the property name of our IHero interface. Then in the first tr last two tr tags we have passed displayedColumns array, and in the last tr, we define an order for our header columns and the row definitions. At first, this implementation may feel overwhelming but later on, you'll get used to it
You'll see the output on the screen like this
Pagination
To add pagination in the current table do the following changes in the existing table
- Add mat-paginator after table tag is closed
app.component.html <mat-paginator #paginator [pageIndex]="0" [pageSize]="5" [pageSizeOptions]="[2, 3, 5]"></mat-paginator>
- Notice the #paginator id on the mat-paginator selector, we will access it through @ViewChild and pass it to our dataSource object
For apps below Angular 8, use the following syntaxapp.component.html @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
app.component.html @ViewChild(MatPaginator) paginator: MatPaginator;
- Assign this paginator to dataSource.paginator property inside ngOnInit life cycle hook
After adding pagination, your code will look like this
import { Component, ViewChild, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { MatTableDataSource, MatSort, MatPaginator } from '@angular/material';
import { IHero } from './app.interfaces';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
displayedColumns = ['id', 'name', 'fullName', 'placeOfBirth', 'publisher'];
dataSource = new MatTableDataSource<IHero>();
constructor(
private httpClient: HttpClient
) { }
ngOnInit() {
this.dataSource.paginator = this.paginator;
this.httpClient.get('http://localhost:3000/heros')
.subscribe((heros: IHero[]) => {
this.dataSource.data = heros;
});
}
}
Sort
To add sorting in the current table do the following changes in the existing table
- Add matSort directive on the table tag
- Add mat-sort-header directive for each header cell that will trigger sorting
- Notice the #sort id on the mat-sort selector, we will access it through @ViewChild and pass it to our dataSource object just like we did in the pagination section
For apps below Angular 8, use the following syntaxapp.component.html @ViewChild(MatSort, { static: true }) sort: MatSort;
app.component.html @ViewChild(MatSort) sort: MatSort;
- Assign this sort to dataSource.sort property inside ngOnInit life cycle hook
After adding sorting, your code will look like this
displayedColumns = ['id', 'name', 'fullName', 'placeOfBirth', 'publisher'];
dataSource = new MatTableDataSource<IHero>();
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(
private httpClient: HttpClient
) { }
ngOnInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.httpClient.get('http://localhost:3000/heros')
.subscribe((heros: IHero[]) => {
this.dataSource.data = heros;
});
}
Filter
In the last step, we are going to add the filter. I will add an input field on which user will enter words, the table records on which searched word is found will only be displayed
- I've added an input field and add added logic to filter the values
app.component.ts <mat-form-field class="filter"> <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter"> </mat-form-field>
- Assign this sort to the dataSource.filter property inside applyFilter method
app.component.html applyFilter(filterValue: string) { this.dataSource.filter = filterValue.trim().toLowerCase(); }
After completing pagination, sorting, and filter, your code will look like this
import { Component, ViewChild, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { MatTableDataSource, MatSort, MatPaginator } from '@angular/material';
import { IHero } from './app.interfaces';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild(MatSort, { static: true }) sort: MatSort;
displayedColumns = ['id', 'name', 'fullName', 'placeOfBirth', 'publisher'];
dataSource = new MatTableDataSource<IHero>();
constructor(
private httpClient: HttpClient
) { }
ngOnInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.httpClient.get('http://localhost:3000/heros')
.subscribe((heros: IHero[]) => {
this.dataSource.data = heros;
});
}
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
}
Conclusion
CONGRATS! You just learned how to add pagination, sort, filter in an Angular material table
If you want to find the whole code for this post. Go to Github
If you would like to get notified when a new post is out, subscribe to push notifications by signing in
If you enjoyed the blog post, share it on social media so others can find it!
If you have any questions, suggestions, or feedback, please leave them in the comments below! It would mean the world to me!!!
Comments (0)