This page looks best with JavaScript enabled

Angular Material Table With Paging, Sorting And Filtering

 ·  β˜• 11 min read  ·  ✍️ Adesh

Here is the link to Angular Material: https://material.angular.io/

Angular Material Table (mat-table)

In this blog, we are going to learn about Angular Material Table, that is, mat-table. The mat-table provides a Material Design styled data-table that can be used to display rows of data.

Setting Up The Angular 7 Project

we are going to use Angular 7 project to work with Angular Material Table component. If you are still working on Angular 6, and wants to upgrade your Angular CLI to Angular 7, here is the below link to upgrade from Angular 6 to Angular 7.

Update Angular 6 to Angular 7 version

Also, here is the link to create your first app in Angular 7 as well.

Creating your first app in Angular 7

Let’s create our Angular 7 Material app using this command.

1
ng new angularmat

In this example, angularmat is our project name. A new project folder is created, the Angular project template is downloaded and the needed dependencies are installed. Once everything is set up, and now you are ready to run your application by using this command.

1
ng serve --open

Now, it’s a time to add Angular Material dependencies in our project.

1. Install Angular Material, Angular CDK And Angular Animations To Angular Project

You can use the npm command to install Angular Material, Angular CDK and Angular Animations to your project.

1
npm install --save @angular/material @angular/cdk @angular/animations

2. Configure Animation By Importing BrowserAnimationsModule

Once the above packages have been installed in your app, the next step is to configure the animation by importing BrowserAnimationsModule in your app.module.ts file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';

@NgModule({
  ......
  imports: [
    BrowserAnimationsModule
  ],
  .....
})
export class AppModule { }

3. Importing Angular Material Theme

It is required to importing the Angular Material theme in your project. Open your project’s filestyles.css, and add this line.

4. Adding Angular Material Icons (optional)

You can use Angular Material Icons in your project. Here is the official link of Material Design Icons. Open your index.html and add this link in this file.

5. Import Angular Material Table (MatTableModule)

Now, in order to use Angular Material Table, you have to import the MatTableModule in your module file. Open the app.module.ts file, and import this statement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import {MatTableModule} from '@angular/material/table';

@NgModule({
  ......
  imports: [
    MatTableModule
  ],
  .....
})
export class AppModule { }

6. Create Mat-Table Data For Display

To display data in our mat-table, let’s first create our sample data interface and populate the data. I am going to create an interface EmployeeData having the following properties. Adding the array of employee’s names and their favorite colors as well.

Adding the array constants of employee’s names and their favorite colors. The getEmployees``() function will return the full employee data to display.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
export interface EmployeeData {
  Id: string;
  EmpName: string; 
  Color: string;
  Hours: number;
}

const FAVORITE_COLORS: string[] = ['gray', 'black', 'navy', 'blue', 'teal', 'green', 'purple',
  'fuchsia', 'lime', 'olive', 'aqua', 'yellow', 'orange', 'red', 'maroon'];
const EMP_NAMES: string[] = ['Robert', 'Jing Jo', 'Thomas', 'Peter', 'Sam', 'Jack',
  'Charlie', 'Maria', 'Julia', 'Albert', 'Arthur', 'James',
  'Simran', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];


//This function will create employee data
function getEmployees(id: number): EmployeeData {
  const name =
  EMP_NAMES[Math.round(Math.random() * (EMP_NAMES.length - 1))] + ' ' +
  EMP_NAMES[Math.round(Math.random() * (EMP_NAMES.length - 1))].charAt(0) + '.';

  return {
    Id: id.toString(),
    EmpName: name,
    Color: FAVORITE_COLORS[Math.round(Math.random() * (FAVORITE_COLORS.length - 1))],
    Hours: 8
  };
}

7. Bind Data to Mat-Table

Once you have setup the data for mat-table, we are now good to go to bind it with mat-table. Let’s import MatTableDataSource in our app.component.ts file.

Fill the `displayedColumns` array with the name of columns to be displayed in our table. Also, mention the EmployeeData interface as our data source. We have created a `emplist` properties, and assigned the 100 employees to this list. Finally, I have passed this `emplist` to our mat-table data source property.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
displayedColumns: string[] = ['Id', 'EmpName', 'Color', 'Hours'];
dataSource: MatTableDataSource<EmployeeData>;

  emplist: any;

  constructor() {
    // Create 100 employees
    this.emplist = Array.from({ length: 100 }, (_, k) => getEmployees(k + 1));  
    // Assign the data to the data source
    this.dataSource = new MatTableDataSource(this.emplist);
  }

7.1 Create mat-table and bind data

Next step to create our html template to bind these properties to `mat-table` component. Here is the syntax of data binding in our app.component.html file.

Write your mat-table and bind the [dataSource] property to it.

1
2
3
<table mat-table [dataSource]="dataSource">
....
</table>

This is the simple form of binding data to mat-table. The table will take the array and render a row for each object in the data array.

7.2 Creating the column template

After creating our mat-table and binding its [dataSource], next step is to create our column template.

Each column should have a unique column name and it will contain the contents of its header and row cells.

1
2
3
4
<ng-container matColumnDef="Id">
      <th mat-header-cell *matHeaderCellDef> ID </th>
      <td mat-cell *matCellDef="let row"> {{row.Id}} </td>
    </ng-container>

In the above sample, we have given the unique name "Id" to our column property matColumnDef. Inside the ng-container, we have defined mat-header-cell for displaying the ID header, and bind the data using {{row.Id}} to mat-cell of our template.

So the complete column bindings will be like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- ID Column -->
    <ng-container matColumnDef="Id">
      <th mat-header-cell *matHeaderCellDef> ID </th>
      <td mat-cell *matCellDef="let row"> {{row.Id}} </td>
    </ng-container>

    <!-- Employee Name Column -->
    <ng-container matColumnDef="EmpName">
      <th mat-header-cell *matHeaderCellDef>Employee Name </th>
      <td mat-cell *matCellDef="let row"> {{row.EmpName}} </td>
    </ng-container>

    <!-- Color Column -->
    <ng-container matColumnDef="Color">
      <th mat-header-cell *matHeaderCellDef> Color </th>
      <td mat-cell *matCellDef="let row"> {{row.Color}} </td>
    </ng-container>

    <!-- Hours Column -->
    <ng-container matColumnDef="Hours">
      <th mat-header-cell *matHeaderCellDef>Hours </th>
      <td mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.Hours}} </td>      
    </ng-container>

7.3 Defining the row template

In the last step, we have to define row template, where we will tell the table which columns be rendered in the header and data rows. For that purpose, we have already created a variable displayedColumn in our component class file.

Add these two lines at the bottom of your mat-table tag to specify, which columns we are going to show.

1
2
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

so the complete html template will be like this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div class="mat-elevation-z8">
  <table mat-table [dataSource]="dataSource">

    <!-- ID Column -->
    <ng-container matColumnDef="Id">
      <th mat-header-cell *matHeaderCellDef> ID </th>
      <td mat-cell *matCellDef="let row"> {{row.Id}} </td>
    </ng-container>

    <!-- Employee Name Column -->
    <ng-container matColumnDef="EmpName">
      <th mat-header-cell *matHeaderCellDef>Employee Name </th>
      <td mat-cell *matCellDef="let row"> {{row.EmpName}} </td>
    </ng-container>

    <!-- Color Column -->
    <ng-container matColumnDef="Color">
      <th mat-header-cell *matHeaderCellDef> Color </th>
      <td mat-cell *matCellDef="let row"> {{row.Color}} </td>
    </ng-container>

    <!-- Hours Column -->
    <ng-container matColumnDef="Hours">
      <th mat-header-cell *matHeaderCellDef>Hours </th>
      <td mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.Hours}} </td>      
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>

Now, it is the time to run your app and see the data in the mat-table. Run ng serve --open in your terminal.

Angular mat-table

Showing 100 of rows in mat-table

Till now, we have implemented our basic mat-table. Now, let’s move to the next feature of mat-table, that is, pagination.

8. Mat-Table Pagination

mat-paginator is used to provide pagination with the mat-table. Each paginator requires two basic things:

  • The number of items per page (default is 50)

  • Total number of items being paged

The paginator displays a dropdown of page sizes for the user to choose from. The options for this dropdown can be set viaΒ pageSizeOptions

The current pageSize will always appear in the dropdown, even if it is not included in `pageSizeOptions`.

To implement the pagination, first of all, import the MatPaginatorModule in your app.module.ts file. Add MatPaginatorModule in imports[] array as well.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import {MatTableModule} from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    .....
    MatTableModule,
    MatPaginatorModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Let’s implement the MatPaginator in our app.component.ts file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource, MatPaginator } from '@angular/material';

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

  @ViewChild(MatPaginator) paginator: MatPaginator;

  constructor() {
    ......
  }

  ngOnInit() {
    this.dataSource.paginator = this.paginator;
  }
}

Also, place <mat-paginator> element on app.component.html file as well.

1
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>

Let me explain you about this pagination control. First of all, we imported ViewChild and MatPaginator in our component class file. Then we accessed our MatPaginator control using @ViewChild(MatPaginator), and in ngOnInit() life-cycle hook, we assigned this paginator to our datasource paginator property.

Don’t forget to put <mat-paginator> with [pageSizeOptions] attribute on component html file.

Mat-table with Pagination

Mat-table with Pagination

9. Mat-Table Sorting

In this step, we are going to implement mat-table sorting feature. Like other modules, we have to first import MatSortModule in our app.module.ts file. Add this MatSortModule in import[] array as well.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import {MatTableModule} from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material';
import {MatSortModule} from '@angular/material/sort';

import { AppComponent } from './app.component';

@NgModule({
  ........
  imports: [
    .....
    MatTableModule,
    MatPaginatorModule,
    MatSortModule
  ],
  ......
})
export class AppModule { }

Now, go to the app.component.html file, add matSort to <table mat-table> tag. Also, we have to add mat-sort-header to each column. Add mat-sort-header to <th mat-header-cell> of each column. The complete html file looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<div class="mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <!-- ID Column -->
    <ng-container matColumnDef="Id">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
      <td mat-cell *matCellDef="let row"> {{row.Id}} </td>
    </ng-container>

    <!-- Employee Name Column -->
    <ng-container matColumnDef="EmpName">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Employee Name </th>
      <td mat-cell *matCellDef="let row"> {{row.EmpName}} </td>
    </ng-container>

    <!-- Color Column -->
    <ng-container matColumnDef="Color">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Color </th>
      <td mat-cell *matCellDef="let row"> {{row.Color}} </td>
    </ng-container>

    <!-- Hours Column -->
    <ng-container matColumnDef="Hours">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Hours </th>
      <td mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.Hours}} </td>      
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>

Notice carefully, where we have added matSort to

..
and mat-sort-header to .. of each column.

Now, move to app.component.ts file, and implement the sorting over there as well.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource, MatPaginator, MatSort } from '@angular/material';

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

  ......
  ngOnInit() {
    .....
    this.dataSource.sort = this.sort;
  }
}

Let me explain this, first of all, we have imported MatSort in our component class file. Then using @ViewChild(MatSort), we accessed our MatSort component, and finally, we assigned sort to datasource sort property.

mat-table sorting

Mat-table sorting

Look at the table headers, you will header a sort arrow on each on mouse hover. In this picture, I sorted Employee Name, and you can an arrow on this column as well.

10. Mat-Table Filtering

In this last point, I am going to show you how to filter your mat-table.

First of all, import these statement in your app.module.ts file, and add MatFormFieldModule and MatInputModule in imports[] array.

1
2
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input';

After importing above modules, let place matInput field on our app.component.html file.

app.component.html

1
2
3
4
<h3>Filter</h3>
<mat-form-field>
  <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>

I have bind an event applyFilter() on matInput keyup() event, which will filter our data. Let’s create our applyFilter() function in the component class file.

app.component.ts

1
2
3
4
5
6
7
applyFilter(filterValue: string) {
    this.dataSource.filter = filterValue.trim().toLowerCase();

    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

mat table filter

Mat-table filtering

The applyFilter() is very simple. It will use the `datasource.filter` property to filter the mat-table, and if we used paginator, it will set the first page as result.

Download

You can download the complete project from Github.

Download Project Files

Summary

In this tutorial, we learned about how to install Angular Material in our Angular app. Then how we can use Mat-Table to display the tabular data. I also demonstrate common features of any data grid like Pagination, Sorting and Filtering.

Further Reading

ng-template, ng-container And ngTemplateOutlet In Angular

Spread Operator In TypeScript

Learn About Observables, Observers And Operators of RxJS – Angular

Share on

Adesh
WRITTEN BY
Adesh
Technical Architect