a.emma
a.emma

Reputation: 735

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

I am using this code

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

So, how to show empty message "No Record found" in data table.

Upvotes: 73

Views: 159754

Answers (20)

Ruthvik Ch
Ruthvik Ch

Reputation: 11

Just as PLPeeters said If you are using Angluar Material >= 10 or more, then you can show a message when no data matches the filter, by using the *matNoDataRow directive, which looks something like this :

 <tr class="mat-row" *matNoDataRow>
  <td class="mat-cell" [attr.colspan]="displayedColumns.length">
    No data matching the filter.
  </td>
</tr>

If you are using Angular Material <10 Then You can use the following code to show data after filtering, if no data is available you can show the row with the text :

      <!-- No Data Found -->
      <ng-container matColumnDef="noDataFound" >
        <td mat-footer-cell *matFooterCellDef colspan="7" [hidden]="dataSource?.filteredData?.length!=0">
          No records found 
        </td>
      </ng-container>

Upvotes: 1

Aniket
Aniket

Reputation: 1122

Inside your table add this

   <tr class="mat-row" *matNoDataRow>
        <td class="mat-cell" colspan="9999">No Transactions yet!</td>
    </tr>

Upvotes: 0

Renjith P N
Renjith P N

Reputation: 4241

With Angular Material 10 or above If you want to show a message when not data matches the filter, you can use the *matNoDataRow directive.

 <tr class="mat-row" *matNoDataRow>
  <td class="mat-cell" [attr.colspan]="displayedColumns.length">
    No data matching the filter.
  </td>
</tr>

Upvotes: 122

Etienne Redelinghuys
Etienne Redelinghuys

Reputation: 91

I was getting a runtime error "Cannot read property 'length' of undefined" if the array was null. Solved it by first checking the null value, and if true it does not proceed to the length test, thus not causing the error. i.e.

<tr *ngFor="let category of _projectCategories">
        <td>
            {{ category.name }}
        </td>
        <td>
            {{ category.description }}
        </td>
        <td>
            {{ category.group }}
        </td>
        <td>
            <i class="nc-icon" [class.nc-check-2]="category.active"
                [class.nc-simple-remove]="!category.active"></i>
        </td>
    </tr>
    <tr *ngIf="(_projectCategories==null) || (_projectCategories.length == 0)">
        <td colspan="2">
            Project currently has no categories.
        </td>
    </tr>

Upvotes: 0

rlv-dan
rlv-dan

Reputation: 1104

My solution does not alter the footer, and shows the message inside of the actual table by using CSS and adding a box :before the footer:

First some CSS:

td.no-content {
  padding-top: 7rem;
}

td.no-content:before {
  content: attr(data-empty-message);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  text-align: center;
  padding: 3rem 0 3rem 0;
  background-color: white;
}

Then add the no-content class to the footer TD when nothing is showing:

<td mat-footer-cell *matFooterCellDef 
    [class.no-content]="dataSource.filteredData.length === 0" 
    data-empty-message="Nothing found..."
>

Upvotes: 0

Mohsin Ejaz
Mohsin Ejaz

Reputation: 414

Step #0

In ts

  dataSource: any = new MatTableDataSource()

Step #1

      <table [dataSource]="dataSource">

        <ng-container matColumnDef="nodata">
          <td mat-footer-row *matFooterCellDef [colSpan]="displayedColumns.length" 
          style="text-align: center;">No Data Available</td>
        </ng-container>

       <tr mat-footer-row 
         [hidden]="dataSource.data.length >0"
        *matFooterRowDef="['nodata']">
       </tr>

     </table>

Upvotes: 5

Mile Mijatović
Mile Mijatović

Reputation: 3177

In your component-name.component.html:

<div class="mat-elevation-z8">
    <mat-table [dataSource]="listData" matSort>
        <ng-container matColumnDef="fullName">
            <mat-header-cell *matHeaderCellDef mat-sort-header>Full Name</mat-header-cell>
            <mat-cell *matCellDef="let element">{{element.fullName}}</mat-cell>
        </ng-container>
        ...
        ...
        <ng-container matColumnDef="noData">
            <mat-footer-cell *matFooterCellDef colspan="6">
                No data.
            </mat-footer-cell>
        </ng-container>

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

        <mat-footer-row *matFooterRowDef="['noData']" [ngClass]="{'hide':!(listData!=null && listData.data.length==0)}"></mat-footer-row>
    </mat-table>
    <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]="5" showFirstLastButtons></mat-paginator>
</div>

In your style.scss or component-name.component.scss define .hide class

.hide { display: none; }

and that's all :)

Upvotes: 5

Ruben
Ruben

Reputation: 9186

this worked for me:

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

<tr mat-footer-row *matFooterRowDef="!dataSource.filteredData.length ? ['noRecords'] : []" colspan="2"></tr>

Also note that it's possible you have to add a <td mat-footer-cell *matFooterCellDef></td> for every row if you already use the footer.

Upvotes: 0

sandy
sandy

Reputation: 448

You can use HTML hidden attribute to achieve same thing

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

Upvotes: 1

alex351
alex351

Reputation: 1966

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>

Upvotes: 2

Saad Joudi
Saad Joudi

Reputation: 623

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>

Upvotes: 1

AshwiniMishra
AshwiniMishra

Reputation: 1

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>

Upvotes: 0

A-Sharabiani
A-Sharabiani

Reputation: 19329

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>

Upvotes: 3

mahval
mahval

Reputation: 2213

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 = []

Upvotes: 27

Sharma Vikram
Sharma Vikram

Reputation: 2470

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>

Upvotes: 10

Ales Vlasak
Ales Vlasak

Reputation: 338

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>

Upvotes: 23

Shivendra Singh
Shivendra Singh

Reputation: 11

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>

Upvotes: 0

Saif Tarar
Saif Tarar

Reputation: 89

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

Upvotes: 8

sadako1287
sadako1287

Reputation: 189

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!

Upvotes: 19

bugs
bugs

Reputation: 15313

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>

Upvotes: 1

Related Questions