Angular Material Table With Paging, Sorting And Filtering

Angular Material Table With Paging, Sorting And Filtering

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.

Angular Material is a collection of Material Design components for an Angular app. You can apply Material Design by using these components very easily. Angular Material became very easy with the release of Angular 6. Here, we will work on Angular Material with Angular 7.

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

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. Update Angular 6 to Angular 7 version Let’s create our Angular 7 Material app using this command.

<em>ng new angularmat</em>

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.

<em>ng serve --open</em>

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.

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.

app.module.ts

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.

styles.css

@import "[email protected]/material/prebuilt-themes/indigo-pink.css";

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 yourindex.html and add this link in this file.

index.html

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

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.

import {MatTableModule} from '@angular/material/table';


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

app.module.ts

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.

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
      };
    }

app.component.ts

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.

app.component.ts

Update Angular 6 to Angular 7 version 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.

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);
      }

app.component.ts

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.

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

app.component.html

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.

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

app.component.html

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:

<!-- 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>

app.component.html

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.

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

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

app.component.html

so the complete html template will be like this.

<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>

app.component.html

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

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.

app.module.ts

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 { }

app.module.ts

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

app.component.ts

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;
      }
    }


    ......

app.component.ts

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

app.component.html

Update Angular 6 to Angular 7 version 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

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.

app.module.ts

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 { }

app.module.ts

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:

app.component.html

<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>

app.component.html

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.

app.component.ts

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;
      }
    }

gistfile1.txt

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 sortproperty.

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.

app.module.ts

Update Angular 6 to Angular 7 version> Update Angular 6 to Angular 7 version After importing above modules, let place matInput field on our app.component.html file.

app.component.html

<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

 applyFilter(filterValue: string) {
        this.dataSource.filter = filterValue.trim().toLowerCase();


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

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

Angular RxJS: Observables, Observers and Operators Introduction

The Pros and Cons of Angular Development

Real Time Apps with TypeScript: Integrating Web Sockets, Node & Angular

Angular 8 - Reactive Forms Validation Example

Angular vs React vs Vue: Which is the Best Choice for 2019?

A comparison between Angular and React

Getting Started with Nx in Angular

angular angular-js javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

What are the differences between the various JavaScript frameworks? E.g. Vue.js, Angular.js, React.js

What are the differences? Do they each have specific use contexts?