How to show empty message in data table angular material, If no data found

It's like bugs is saying, you can just use *ngIf. Compare these two tables here:

https://stackblitz.com/edit/angular-w9ckf8

<mat-toolbar color="primary">My empty table</mat-toolbar>

<mat-table #table [dataSource]="dataSourceEmpty" matSort *ngIf="dataSourceEmpty.length > 0">
    <ng-container matColumnDef="Name">
        <mat-header-cell *matHeaderCellDef mat-sort-header>Name </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="Age">
        <mat-header-cell *matHeaderCellDef mat-sort-header>Age </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.age}} </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="row.toggle(row)">
    </mat-row>
</mat-table>

<div *ngIf="dataSourceEmpty.length === 0">No records found</div>

<hr>

<mat-toolbar color="primary">My full table</mat-toolbar>

<mat-table #table [dataSource]="dataSource" matSort *ngIf="dataSource.length > 0">
    <ng-container matColumnDef="Name">
        <mat-header-cell *matHeaderCellDef mat-sort-header>Name </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
    </ng-container>

    <ng-container matColumnDef="Age">
        <mat-header-cell *matHeaderCellDef mat-sort-header>Age </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.age}} </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="row.toggle(row)">
    </mat-row>
</mat-table>

<div *ngIf="dataSource.length === 0">No data</div>

TS with data:

displayedColumns = ['Name', 'Age']
dataSource = [{name:'Sara',age:17}, {name: 'John', age: 20}]
dataSourceEmpty = []

If you console.log dataSource, you will see the following: dataSource example

It is not the dataSource itself that is the array, but dataSource.data. dataSource is actually a class that has a property data that contains what you pass into MatTableDataSource (https://github.com/angular/material2/blob/master/src/lib/table/table-data-source.ts) Therefore, this is what you should be using for your *ngIf statement.

<div *ngIf="dataSource.data.length === 0">
No Records Found!
</div>

Hope this helps!

Sharma Vikram

There are two ways to show error message in html

1st method using If method

<div *ngIf="dataSource.length">
  <mat-table #table [dataSource]="dataSource" matSort >
  <ng-container matColumnDef="tache">
    <mat-header-cell *matHeaderCellDef mat-sort-header> tâche </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.tache}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="outil">
    <mat-header-cell *matHeaderCellDef mat-sort-header> outil </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.outil}} </mat-cell>
  </ng-container>  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="selection.toggle(row)">
  </mat-row>
</mat-table>
</div>

<div *ngIf="!dataSource.length">
No Record found
</div>

2nd Method Using If else

<div *ngIf="dataSource.length; else noRecord">
  <mat-table #table [dataSource]="dataSource" matSort >
  <ng-container matColumnDef="tache">
    <mat-header-cell *matHeaderCellDef mat-sort-header> tâche </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.tache}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="outil">
    <mat-header-cell *matHeaderCellDef mat-sort-header> outil </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.outil}} </mat-cell>
  </ng-container>  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="selection.toggle(row)">
  </mat-row>
</mat-table>
</div>

<ng-template #noRecord>
 <div>
  No Record found
  </div>
</ng-template>
Saif Tarar
<mat-footer-row *matFooterRowDef="['noData']" [ngClass]="{'hide':!(listData!=null && listData.filteredData.length==0)}"></mat-footer-row>

I was able to solve the problem by doing this. hide is a custom css

.hide{
    display:none;
} 
Ales Vlasak

You can put it in the footer row this way:

Column definition:

<ng-container matColumnDef="noRecord">
      <td mat-footer-cell *matFooterCellDef>No records found.</td>
</ng-container>

Footer row definition:

<ng-template [ngIf]="dataSource.data.length === 0">
    <tr mat-footer-row *matFooterRowDef="['noRecord']"></tr>
</ng-template>

In newer Angular versions don't forget datasource.data if your datasource is of type MatTableDataSource.

Example:

In the TypeScript file:

// ...
datasource = new MatTableDataSource<object>([]);
// ...

And in the HTML file:

<div *ngIf="datasource.data.length > 0"> 
  <!--Show the table.-->
</div>

<div *ngIf="datasource.data.length === 0">
 <!--Show table is empty message. -->
</div>

You can simply use the *ngIf directive to check if dataSource is not empty.

 <mat-table *ngIf="dataSource.length > 0" #table [dataSource]="dataSource" matSort >
  <ng-container matColumnDef="tache">
    <mat-header-cell *matHeaderCellDef mat-sort-header> tâche </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.tache}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="outil">
    <mat-header-cell *matHeaderCellDef mat-sort-header> outil </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.outil}} </mat-cell>
  </ng-container>  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="selection.toggle(row)">
  </mat-row>
</mat-table>

<p *ngIf="dataSource.length === 0">No records found</p>

In .ts file

if (this.dataSource.length == 0) {
    this.noDataMessage = true;
} else {
    this.noDataMessage = false;
}

In .html file

<div *ngIf="noDataMessage">
    <p>{{ 'label.DataNotAvailable' | translate }}</p>
</div>

For anyone having the option to do this in the Footer, I have been able to do this by doing following steps in Angular 6/7/8:

1) In your [ComponentName].component.html

<table mat-table [dataSource]="dataSourceTable">
    <ng-container matColumnDef="columneName">
            <th mat-header-cell *matHeaderCellDef> Name </th>
            <td mat-cell *matCellDef="let element"> {{element.columnname}} </td>
            <td mat-footer-cell *matFooterCellDef>
                <!-- Display a download button in the footer when data is available-->
                <button mat-raised-button color="primary" 
*ngIf="dataSourceTable.data.length > 0">Download</button>
                <!--Below code is displayed when there is no data-->
                <a mat-button *ngIf="dataSourceTable.data.length === 0">No Data 
Found</a>
            </td>
        </ng-container>
        <!--Below Lines of code generates Header, Row and footer for your table  -->
        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true;"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;">
        </tr>
        <tr mat-footer-row *matFooterRowDef="displayedColumns; sticky: true"></tr>
    </table>

You can add a condition on your dataSource directly without having to access the data or its length:

<div *ngIf="!yourDataSource" class="alert alert-primary" role="alert">No data </div>

If anyone uses filter with dataSource, you should watch for dataSource.filteredData.length.

i.e.

if (this.dataSource.filteredData.length < 1) {
  this.presentDialog();
}

or

<div class="container" *ngIf="dataSource.filteredData.length < 1">
    // Your message here...
</div>