Angular material table with searching sorting and pagination

Hey guys, in this post we are going to see how to implement a material table in your angular project.  Herewith the material table, we are going to add a few basic features like searching, sorting, and pagination, etc. Let’s do it step by step.
[you will get a link to download the project at bottom]


[If you have any problem related to the Angular material table please check our following posts:
Click here for add - remove columns dynamically in the angular material table,
Click here for inline editing and validation with template-driven forms in the angular material table,
Click here for multiple expandable rows in the angular material table,
Click here for a table inside a row and multiple paginators in the angular material table,
Click here for adding custom and common filter/search in the angular material table]

At the very first to use the material we have to install angular material and it depends on CDK so we have to install angular CDK as well.



Commands :
npm install –save @angular/material @angular/cdk


Now add material to your project
Commands:
ng add @angular/material

 While adding material it will ask for a few things like, which theme you want? And hammer js for gesture recognition. Select as per your need.
For implementation, we are refering our previos example here.
homepage.component.html
<div class="body">
  <div class="row">
    <div class="align-items-center col-lg-12 btn-outline-light">
Material Table Demo
    </div><br><br>
  </div>
  <form #testForm="ngForm">
  <div class="row">
  <div class="col-lg-2"></div>
  <div class="col-lg-8 center">
  <div class="spinner-container"                                         *ngIf="userListMatTabDataSource.loading$ | async">
  <mat-spinner></mat-spinner>
  </div>
<div class="card">
  <div class="thead">
    <label for="Table">Demo Table</label>
    <input type="text" style="float:right" (keyup)="applyFilter($event.target.value)" placeholder="search for" class="form-control-sm top-margin">
</div>
<mat-table class="mat-elevation-z8" [dataSource]="userListMatTabDataSource" matSort matSortActive="userName"
matSortDirection="asc" matSortDisableClear>
<ng-container matColumnDef="action">
<mat-header-cell *matHeaderCellDef>Sr No</mat-header-cell>
<mat-cell *matCellDef="let user; let i = index;">
{{i+1}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="userName">
<mat-header-cell *matHeaderCellDef mat-sort-header>User Name</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.userName}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="email">
<mat-header-cell *matHeaderCellDef mat-sort-header>Email</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.email}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="contactNo">
<mat-header-cell *matHeaderCellDef mat-sort-header>Contact No</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.contactNo}}
</mat-cell>
</ng-container>
<ng-container matColumnDef="address">
<mat-header-cell *matHeaderCellDef mat-sort-header>Address</mat-header-cell>
<mat-cell *matCellDef="let user">
{{user.address}}
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="columnList"></mat-header-row>
<mat-row *matRowDef="let row; columns: columnList; let i = index;" [class.selected]="selectedRow == row.id"
(click)="rowClick(row.id)">
</mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[3, 5, 10]" showFirstLastButtons></mat-paginator>
</div>
</div>
</div>
</form>
</div>


homepage.component.ts
import { Component, OnInit, Input, ViewChild } from '@angular/core';
import { User } from '../user/user';
import { MatPaginator, MatTableDataSource, MatSort } from '@angular/material';
import { environment } from 'src/environments/environment';

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

  userList: User[];
  selectedRow: Number;
  editedRows: Boolean[];
  private columnList = ["action", "userName", "email", "contactNo", "address"];
  userListMatTabDataSource = new MatTableDataSource<User>(this.userList);

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor() { }

  ngOnInit() {
    this.editedRows = [];
    this.getAlldata();
    this.userListMatTabDataSource.paginator = this.paginator;
    this.userListMatTabDataSource.sort = this.sort;
  }

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

  getAlldata() {
    this.userList = [
      { id: 1, userName: "Ramesh", password: "rebqwtye", email: "ramesh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined },
      { id: 2, userName: "Suresh", password: "rebqwtye", email: "suresh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined },
      { id: 3, userName: "Ganesh", password: "rebqwtye", email: "ganesh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined },
      { id: 4, userName: "Bhavesh", password: "rebqwtye", email: "bhavesh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined },
      { id: 5, userName: "Bhavesh", password: "rebqwtye", email: "bhavesh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined },
      { id: 6, userName: "Bhavesh", password: "rebqwtye", email: "bhavesh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined },
      { id: 7, userName: "Bhavesh", password: "rebqwtye", email: "bhavesh@gmail.com", contactNo: "9788235466", address: "123 RG Road, XYCity", edited: undefined }
    ];
    this.userListMatTabDataSource.data = this.userList;
  }

  rowClick(rowId) {
    this.selectedRow = rowId;
  }

}

Now let's check the code step by step
At first, the data source of the material table, when we use the normal table we use a loop, and iterate all the data and populate the table. But with the mat table, we just let know the mat table from where to access data, it will take care of other things for us.

In HTML
[dataSource]="userListMatTabDataSource"

But we need to create that data source first

In ts
userListMatTabDataSource = new MatTableDataSource<User>(this.userList);

here we have created a data source of type user(because we are going to show users in our table) and passed our data in a bracket (it's optional we can pass data later).
We are ready with a data source, but the mat table needs one more thing to get started. We need to specify the columns which we are going to display in the table.

In ts
private columnList = ["action", "userName", "email", "contactNo", "address"];

and to get done with columns, we have to specify column list for material header row defination to specify headers of table(column names) as well as row defination of column(column data).
<mat-header-row *matHeaderRowDef="columnList"></mat-header-row>
<mat-row *matRowDef="let row; columns: columnList; let i = index;" [class.selected]="selectedRow == row.id"
          (click)="rowClick(row.id)">
</mat-row>


Once we are done with defining column names and column object, we have to define what each column contains inside the table, with help of material column definition.
<ng-container matColumnDef="userName">
    <mat-header-cell *matHeaderCellDef >User Name</mat-header-cell>
       <mat-cell *matCellDef="let user">
                  {{user.userName}}
        </mat-cell>
 </ng-container>


Here *matCellDef="let user" we get access to the single object from the data source and we can display any field from that object.
We are ready with a simple material table, Now add some features to the table.
Let's add sorting, add a sort to header i.e mat-sort-header

<mat-header-cell *matHeaderCellDef mat-sort-header>User Name</mat-header-cell>

In ts
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
    this.userListMatTabDataSource.sort = this.sort;
  }

Declare and initialize sorting in ts, now we will get sort arrow and will sort data according to that.
Lets go for pagination
<mat-paginator [pageSizeOptions]="[3, 5, 10]" showFirstLastButtons></mat-paginator>

Here we can define page size’s and navigation button

@ViewChild(MatPaginator) paginator: MatPaginator;
ngOnInit() {
    this.userListMatTabDataSource.paginator = this.paginator;
  }

Declare and initialize pagination and it will work smoothly
And most important is searching because whenever there is large data we must need a search option.

 <input type="text" style="float:right" (keyup)="applyFilter($event.target.value)" placeholder="search for" class="form-control-sm top-margin">

Here we need some mechanism to get it to work, we need to filter data on leaving of each keystroke

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

this is the module file to let you know all the imports and dependencies.

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FirstPageComponent } from './first-page/first-page.component';
import { SecondPageComponent } from './second-page/second-page.component';
import { FormsModule } from '@angular/forms';
import { HomepageComponent } from './homepage/homepage.component';
import { MatTableModule, MatPaginatorModule, MatProgressSpinnerModule, MatFormFieldModule, MatInputModule, MatSortModule, MatButtonModule } from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
declarations: [
AppComponent,
FirstPageComponent,
SecondPageComponent,
HomepageComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
MatTableModule,
MatPaginatorModule,
MatProgressSpinnerModule,
MatInputModule,
MatButtonModule,
MatFormFieldModule,
BrowserAnimationsModule,
MatSortModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }





Output


We are done with material data table implementation, if you need advanced options like inline editing with validation in the table, check our next post.
[download the project here get me the project]

Comments

  1. I like your post very much. It is very much useful for my research. I hope you to share more info about this. Keep posting angular training

    ReplyDelete
  2. hi like your post, i tried it in my application and its working fine.
    Now i wanted to create multiple mat tables with sorting.
    i am generating tables according to my array, so number of tables are not fixed, can you please suggest me the solution to do that.|

    ReplyDelete
    Replies
    1. For sorting it will be very easy, add sorting property and for pagination you have to take care of multiple paginators. This post will help you https://www.angulareasily.com/2020/03/table-inside-row-and-multiple-material.html

      Delete
  3. Thanks for sharing this information. I really Like Very Much.
    angular js online training

    ReplyDelete
  4. Thanks for Sharing your knowledge through post. It's very useful for our development. Could you please help us to provide example for Multiple sorting . for example in above example i like to sort username (asc), email (dec).

    ReplyDelete
  5. Hi, Want to do multiple column sorting like OrderBy(UserName).ThenBy(SLNo) any idea?

    ReplyDelete

Post a Comment