Angular Material Datatable | ‘No Records Found!’ & Hide Pagination

In this Angular 9/8 Material tutorial, we’ll discuss how to show a ‘No records found!‘ message when there is no data to show in the data list and also hide the pagination.

Angular Material’s Datatables is a well-equipped component to show data in tables with lots of features like Sorting, Data filtration, Pagination Column freeze, etc. But believe me or not it lacks a very basic user experience. Yes! you got it right.

I just want to show a message to a gazing soul that there is nothing found my friend…

How to show a small UX enhancing ‘No data found!’ message in the Material Datatable Grid?

I tried to dig into the Table and Paginator API’s but nothing was there to solve this simple and very basic UX.

DISCLAIMER: This is my method and how I resolved the situation in my case, I don’t know if this is the best ever thing that can be done to achieve this. If you people find something more useful please save humanity.

 

 

Ok Fun Ends!

Let’s do it!

Create a simple Angular Material Datatable

First, to make it super clear let’s create a datatable with super simple data

Add following template HTML in the component

<button mat-button (click)="removeRow()">Remove Row 1 by 1</button>

  <div>
    <table mat-table matSort [dataSource]="dataSource">
      <tbody>
        <ng-container matColumnDef="position">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
          <td mat-cell *matCellDef="let element"> {{element.position}} </td>
        </ng-container>

        <ng-container matColumnDef="name">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
          <td mat-cell *matCellDef="let element"> {{element.name}} </td>
        </ng-container>

        <ng-container matColumnDef="weight">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
          <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
        </ng-container>

        <ng-container matColumnDef="symbol">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Symbol </th>
          <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </tbody>
    </table>
    <table>
      <tr *ngIf="!dataSource.data.length">
        <td style="text-align: center;" [attr.colspan]="displayedColumnsH3UDeptList.length">
          No Records Found!
        </td>
      </tr>
    </table>
  </div>
  <mat-paginator [pageSize]="5" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>

We also have a <button> with removeData() method to remove rows one by one.

 

Now update the component class with the following code to create a nice looking Material Grid

// app.component.ts
import { Component, ViewChild } from '@angular/core';

import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
  { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
  { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
  { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
  { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
  { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
  { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
  { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
  { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
  { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'angular-material-data-table';

  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort: MatSort;

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

  removeRow() {
    const data = this.dataSource.data.slice();
    data.shift();
    this.dataSource.data = data;
  }

}

Awsome now we have it … look

The Problem

Try to delete rows 1 by 1 by clicking the button above. You are left with employ Datatable and pagination below which look like this :/

Not so cool …

 

Let’s move to solutions to our two problems.

1) Show ‘No Records Found!’ message

2)  Hide Pagination if there are no records to paginate over.

 

How to Show ‘No Records Found!’ Message in Angular Material Datatable?

Just place another table…

Awkward silence

Yeah, its the only meaningful solution right now …

It will look like this

<div>
    <table mat-table matSort [dataSource]="dataSource">
      <tbody>
        <ng-container matColumnDef="position">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
          <td mat-cell *matCellDef="let element"> {{element.position}} </td>
        </ng-container>

        <ng-container matColumnDef="name">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
          <td mat-cell *matCellDef="let element"> {{element.name}} </td>
        </ng-container>

        <ng-container matColumnDef="weight">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
          <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
        </ng-container>

        <ng-container matColumnDef="symbol">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Symbol </th>
          <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
      </tbody>
    </table>
    
    <table>
      <tr *ngIf="!dataSource.data.length">
        <td style="text-align: center;" [attr.colspan]="displayedColumns.length">
          No Records Found!
        </td>
      </tr>
    </table>

  </div>
  <mat-paginator [pageSize]="5" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>

In the second table, we are having the *ngIf condition on <tr> to check if any row is there in the dataSource. The <td> will have [attr.colspan] equal to the number of columns to merge cells, so that the message will remain in the center of the table always.

Now you will see the message when there is no row in the datatable

How to hide Pagination in Angular Material Datatable if there is no row?

For this, we will simply add the [hidden] directive of Angular to show/ hide the element based on the boolean value provided. The [hidden] simply adds hidden attribute with style set to display:none if you are using bootstrap.css.

Or simply add this style

[hidden] {
    display: none !important;
}

Update the <mat-paginator> directive component as shown below:

<mat-paginator 
    [hidden]="!dataSource.data.length" 
    [pageSize]="5" 
    [pageSizeOptions]="[5, 10, 15]" 
    showFirstLastButtons
  >
  </mat-paginator>

That’s it

 

Conclusion

We are done! we got to learn a trick actually two to make Material data tables more awsome by showing ‘No Records Found!’ message and hide pagination when there are no records available to show.

Hope you liked this post, do share with others, and comment with your thoughts…

3 thoughts on “Angular Material Datatable | ‘No Records Found!’ & Hide Pagination”

Leave a Reply to kalpi Cancel Reply

Your email address will not be published. Required fields are marked *