Datatables

Angular Bootstrap 5 Datatables

The Datatable is a component which mix tables with advanced options like searching, sorting and pagination.

Note: Read the API tab to find all available options and advanced customization

Video tutorial


Basic example

Name Position Office Age Start date Salary
Tiger Nixon System Architect Edinburgh 61 2011/04/25 $320,800
Sonya Frost Software Engineer Edinburgh 23 2008/12/13 $103,600
Jena Gaines Office Manager London 30 2008/12/19 $90,560
Quinn Flynn Support Lead Edinburgh 22 2013/03/03 $342,000
Charde Marshall Regional Director San Francisco 36 2008/10/16 $470,600
Haley Kennedy Senior Marketing Designert London 43 2012/12/18 $313,500
Tatyana Fitzpatrick Regional Director London 19 2010/03/17 $385,750
Michael Silva Marketing Designer London 66 2012/11/27 $198,500
Paul Byrd Chief Financial Officer (CFO) New York 64 2010/06/09 $725,000
Gloria Little Systems Administrator New York 59 2009/04/10 $237,500
Garrett Winters Accountant Tokyo 63 2011/07/25 $170,750
Quinn Flynn Support Lead Edinburgh 22 2013/03/03 $342,000
Ashton Cox Junior Technical Author San Francisco 66 2009/01/12 $86,000
Cedric Kelly Senior Javascript Developer Edinburgh 22 2012/03/29 $433,060
Airi Satou Accountant Tokyo 33 2008/11/28 $162,700
Brielle Williamson Integration Specialist New York 61 2012/12/02 $372,000
        
            
            <div class="datatable mt-4">
              <table
                class="table datatable-table"
                mdbTable
                mdbTableSort
                #table="mdbTable"
                #sort="mdbTableSort"
                [dataSource]="dataSource"
                [pagination]="pagination"
                [sort]="sort"
              >
                <thead class="datatable-header">
                  <tr>
                    <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                      {{ header | titlecase }}
                    </th>
                  </tr>
                </thead>
                <tbody class="datatable-body">
                  <tr *ngFor="let data of table.data" scope="row">
                    <td>
                      {{ data.name }}
                    </td>
                    <td>
                      {{ data.position }}
                    </td>
                    <td>
                      {{ data.office }}
                    </td>
                    <td>
                      {{ data.age }}
                    </td>
                    <td>
                      {{ data.startDate }}
                    </td>
                    <td>
                      {{ data.salary }}
                    </td>
                  </tr>
                </tbody>
              </table>
              <mdb-table-pagination #pagination></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component } from '@angular/core';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              startDate: string;
              salary: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

              dataSource: Person[] = [
                {
                  name: 'Tiger Nixon',
                  position: 'System Architect',
                  office: 'Edinburgh',
                  age: 61,
                  startDate: '2011/04/25',
                  salary: '$320,800',
                },
                {
                  name: 'Sonya Frost',
                  position: 'Software Engineer',
                  office: 'Edinburgh',
                  age: 23,
                  startDate: '2008/12/13',
                  salary: '$103,600',
                },
                {
                  name: 'Jena Gaines',
                  position: 'Office Manager',
                  office: 'London',
                  age: 30,
                  startDate: '2008/12/19',
                  salary: '$90,560',
                },
                {
                  name: 'Quinn Flynn',
                  position: 'Support Lead',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2013/03/03',
                  salary: '$342,000',
                },
                {
                  name: 'Charde Marshall',
                  position: 'Regional Director',
                  office: 'San Francisco',
                  age: 36,
                  startDate: '2008/10/16',
                  salary: '$470,600',
                },
                {
                  name: 'Haley Kennedy',
                  position: 'Senior Marketing Designer',
                  office: 'London',
                  age: 43,
                  startDate: '2012/12/18',
                  salary: '$313,500',
                },
                {
                  name: 'Tatyana Fitzpatrick',
                  position: 'Regional Director',
                  office: 'London',
                  age: 19,
                  startDate: '2010/03/17',
                  salary: '$385,750',
                },
                {
                  name: 'Michael Silva',
                  position: 'Marketing Designer',
                  office: 'London',
                  age: 66,
                  startDate: '2012/11/27',
                  salary: '$198,500',
                },
                {
                  name: 'Paul Byrd',
                  position: 'Chief Financial Officer (CFO)',
                  office: 'New York',
                  age: 64,
                  startDate: '2010/06/09',
                  salary: '$725,000',
                },
                {
                  name: 'Gloria Little',
                  position: 'Systems Administrator',
                  office: 'New York',
                  age: 59,
                  startDate: '2009/04/10',
                  salary: '$237,500',
                },
                {
                  name: 'Garrett Winters',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 63,
                  startDate: '2011/07/25',
                  salary: '$170,750',
                },
                {
                  name: 'Ashton Cox',
                  position: 'Junior Technical Author',
                  office: 'San Francisco',
                  age: 66,
                  startDate: '2009/01/12',
                  salary: '$86,000',
                },
                {
                  name: 'Cedric Kelly',
                  position: 'Senior Javascript Developer',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2012/03/29',
                  salary: '$433,060',
                },
                {
                  name: 'Airi Satou',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 33,
                  startDate: '2008/11/28',
                  salary: '$162,700',
                },
                {
                  name: 'Brielle Williamson',
                  position: 'Integration Specialist',
                  office: 'New York',
                  age: 61,
                  startDate: '2012/12/02',
                  salary: '$372,000',
                },
              ];
            }
          
        
    



Selectable rows

You can easily build datatable with selectable rows.

        
            
          <div class="datatable mt-4">
            <table
            class="table datatable-table"
            mdbTable
            mdbTableSort
            #table="mdbTable"
            #sort="mdbTableSort"
            [dataSource]="dataSource"
            [sort]="sort"
            [pagination]="pagination"
            >
              <thead class="datatable-header">
                <tr>
                  <th scope="col">
                    <div class="form-check d-flex align-items-center mb-0">
                      <input
                      mdbCheckbox
                      class="datatable-header-checkbox form-check-input"
                      type="checkbox"
                      [checked]="allRowsSelected()"
                      (checkboxChange)="toggleAll($event)"
                      />
                    </div>
                  </th>
                  <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                    {{ header | titlecase }}
                  </th>
                </tr>
              </thead>
              <tbody class="datatable-body">
                <tr
                *ngFor="let data of table.data"
                  scope="row"
                  [class.active]="selections.has(data)"
                >
                  <td>
                    <div class="form-check">
                      <input
                      mdbCheckbox
                      (click)="$event.stopPropagation()"
                      (checkboxChange)="toggleSelection($event, data)"
                      [checked]="selections.has(data)"
                      class="datatable-row-checkbox form-check-input"
                      type="checkbox"
                      />
                    </div>
                  </td>
                  <td>
                    {{ data.name }}
                  </td>
                  <td>
                    {{ data.position }}
                  </td>
                  <td>
                    {{ data.office }}
                  </td>
                  <td>
                    {{ data.age }}
                  </td>
                  <td>
                    {{ data.startDate }}
                  </td>
                  <td>
                    {{ data.salary }}
                  </td>
                </tr>
              </tbody>
            </table>
            <mdb-table-pagination #pagination></mdb-table-pagination>
          </div>
          
        
    
        
            
            import { Component } from '@angular/core';
            import { MdbCheckboxChange } from 'mdb-angular-ui-kit/checkbox';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              startDate: string;
              salary: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              selections = new Set<Person>();

              headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

              dataSource: Person[] = [
                {
                  name: 'Tiger Nixon',
                  position: 'System Architect',
                  office: 'Edinburgh',
                  age: 61,
                  startDate: '2011/04/25',
                  salary: '$320,800',
                },
                {
                  name: 'Sonya Frost',
                  position: 'Software Engineer',
                  office: 'Edinburgh',
                  age: 23,
                  startDate: '2008/12/13',
                  salary: '$103,600',
                },
                {
                  name: 'Jena Gaines',
                  position: 'Office Manager',
                  office: 'London',
                  age: 30,
                  startDate: '2008/12/19',
                  salary: '$90,560',
                },
                {
                  name: 'Quinn Flynn',
                  position: 'Support Lead',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2013/03/03',
                  salary: '$342,000',
                },
                {
                  name: 'Charde Marshall',
                  position: 'Regional Director',
                  office: 'San Francisco',
                  age: 36,
                  startDate: '2008/10/16',
                  salary: '$470,600',
                },
                {
                  name: 'Haley Kennedy',
                  position: 'Senior Marketing Designer',
                  office: 'London',
                  age: 43,
                  startDate: '2012/12/18',
                  salary: '$313,500',
                },
                {
                  name: 'Tatyana Fitzpatrick',
                  position: 'Regional Director',
                  office: 'London',
                  age: 19,
                  startDate: '2010/03/17',
                  salary: '$385,750',
                },
                {
                  name: 'Michael Silva',
                  position: 'Marketing Designer',
                  office: 'London',
                  age: 66,
                  startDate: '2012/11/27',
                  salary: '$198,500',
                },
                {
                  name: 'Paul Byrd',
                  position: 'Chief Financial Officer (CFO)',
                  office: 'New York',
                  age: 64,
                  startDate: '2010/06/09',
                  salary: '$725,000',
                },
                {
                  name: 'Gloria Little',
                  position: 'Systems Administrator',
                  office: 'New York',
                  age: 59,
                  startDate: '2009/04/10',
                  salary: '$237,500',
                },
                {
                  name: 'Garrett Winters',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 63,
                  startDate: '2011/07/25',
                  salary: '$170,750',
                },
                {
                  name: 'Ashton Cox',
                  position: 'Junior Technical Author',
                  office: 'San Francisco',
                  age: 66,
                  startDate: '2009/01/12',
                  salary: '$86,000',
                },
                {
                  name: 'Cedric Kelly',
                  position: 'Senior Javascript Developer',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2012/03/29',
                  salary: '$433,060',
                },
                {
                  name: 'Airi Satou',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 33,
                  startDate: '2008/11/28',
                  salary: '$162,700',
                },
                {
                  name: 'Brielle Williamson',
                  position: 'Integration Specialist',
                  office: 'New York',
                  age: 61,
                  startDate: '2012/12/02',
                  salary: '$372,000',
                },
              ];

              allRowsSelected(): boolean {
                const selectionsLength = this.selections.size;
                const dataLength = this.dataSource.length;
                return selectionsLength === dataLength;
              }

              toggleSelection(event: MdbCheckboxChange, value: Person): void {
                if (event.checked) {
                  this.select(value);
                } else {
                  this.deselect(value);
                }
              }

              toggleAll(event: MdbCheckboxChange): void {
                if (event.checked) {
                  this.dataSource.forEach((row: Person) => {
                    this.select(row);
                  });
                } else {
                  this.dataSource.forEach((row: Person) => {
                    this.deselect(row);
                  });
                }
              }

              select(value: Person): void {
                if (!this.selections.has(value)) {
                  this.selections.add(value);
                }
              }

              deselect(value: Person): void {
                if (this.selections.has(value)) {
                  this.selections.delete(value);
                }
              }
            }
          
        
    

Scroll

Setting maximum height/width will enable vertical/horizontal scrolling.

        
            
            <div class="datatable mt-4">
              <div
                class="datatable-inner"
                mdbScrollbar
                style="position: relative; width: 600px; height: 500px"
              >
                <table
                  class="table datatable-table"
                  mdbTable
                  mdbTableSort="mdbTableSort"
                  #table="mdbTable"
                  #sort="mdbTableSort"
                  [dataSource]="dataSource"
                  [sort]="sort"
                  [pagination]="pagination"
                >
                  <thead class="datatable-header">
                    <tr>
                      <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                        {{ header | titlecase }}
                      </th>
                    </tr>
                  </thead>
                  <tbody class="datatable-body">
                    <tr *ngFor="let data of table.data" scope="row">
                      <td>
                        {{ data.name }}
                      </td>
                      <td>
                        {{ data.position }}
                      </td>
                      <td>
                        {{ data.office }}
                      </td>
                      <td>
                        {{ data.age }}
                      </td>
                      <td>
                        {{ data.startDate }}
                      </td>
                      <td>
                        {{ data.salary }}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
              <mdb-table-pagination #pagination style="width: 600px"></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component } from '@angular/core';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              startDate: string;
              salary: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

              dataSource: Person[] = [
                {
                  name: 'Tiger Nixon',
                  position: 'System Architect',
                  office: 'Edinburgh',
                  age: 61,
                  startDate: '2011/04/25',
                  salary: '$320,800',
                },
                {
                  name: 'Sonya Frost',
                  position: 'Software Engineer',
                  office: 'Edinburgh',
                  age: 23,
                  startDate: '2008/12/13',
                  salary: '$103,600',
                },
                {
                  name: 'Jena Gaines',
                  position: 'Office Manager',
                  office: 'London',
                  age: 30,
                  startDate: '2008/12/19',
                  salary: '$90,560',
                },
                {
                  name: 'Quinn Flynn',
                  position: 'Support Lead',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2013/03/03',
                  salary: '$342,000',
                },
                {
                  name: 'Charde Marshall',
                  position: 'Regional Director',
                  office: 'San Francisco',
                  age: 36,
                  startDate: '2008/10/16',
                  salary: '$470,600',
                },
                {
                  name: 'Haley Kennedy',
                  position: 'Senior Marketing Designer',
                  office: 'London',
                  age: 43,
                  startDate: '2012/12/18',
                  salary: '$313,500',
                },
                {
                  name: 'Tatyana Fitzpatrick',
                  position: 'Regional Director',
                  office: 'London',
                  age: 19,
                  startDate: '2010/03/17',
                  salary: '$385,750',
                },
                {
                  name: 'Michael Silva',
                  position: 'Marketing Designer',
                  office: 'London',
                  age: 66,
                  startDate: '2012/11/27',
                  salary: '$198,500',
                },
                {
                  name: 'Paul Byrd',
                  position: 'Chief Financial Officer (CFO)',
                  office: 'New York',
                  age: 64,
                  startDate: '2010/06/09',
                  salary: '$725,000',
                },
                {
                  name: 'Gloria Little',
                  position: 'Systems Administrator',
                  office: 'New York',
                  age: 59,
                  startDate: '2009/04/10',
                  salary: '$237,500',
                },
                {
                  name: 'Garrett Winters',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 63,
                  startDate: '2011/07/25',
                  salary: '$170,750',
                },
                {
                  name: 'Ashton Cox',
                  position: 'Junior Technical Author',
                  office: 'San Francisco',
                  age: 66,
                  startDate: '2009/01/12',
                  salary: '$86,000',
                },
                {
                  name: 'Cedric Kelly',
                  position: 'Senior Javascript Developer',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2012/03/29',
                  salary: '$433,060',
                },
                {
                  name: 'Airi Satou',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 33,
                  startDate: '2008/11/28',
                  salary: '$162,700',
                },
                {
                  name: 'Brielle Williamson',
                  position: 'Integration Specialist',
                  office: 'New York',
                  age: 61,
                  startDate: '2012/12/02',
                  salary: '$372,000',
                },
              ];
            }
          
        
    

Fixed header

Use the fixedHeader option to ensure that a table's header is always visible while scrolling.

        
            
            <div class="datatable mt-4">
              <div class="datatable-inner" mdbScrollbar style="position: relative; max-height: 300px">
                <table
                  class="table datatable-table"
                  mdbTable
                  mdbTableSort
                  #table="mdbTable"
                  #sort="mdbTableSort"
                  [dataSource]="dataSource"
                  [fixedHeader]="true"
                  [sort]="sort"
                  [pagination]="pagination"
                >
                  <thead class="datatable-header">
                    <tr>
                      <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                        {{ header | titlecase }}
                      </th>
                    </tr>
                  </thead>
                  <tbody class="datatable-body">
                    <tr *ngFor="let data of table.data" scope="row">
                      <td>
                        {{ data.name }}
                      </td>
                      <td>
                        {{ data.position }}
                      </td>
                      <td>
                        {{ data.office }}
                      </td>
                      <td>
                        {{ data.age }}
                      </td>
                      <td>
                        {{ data.startDate }}
                      </td>
                      <td>
                        {{ data.salary }}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
              <mdb-table-pagination #pagination></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component } from '@angular/core';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              startDate: string;
              salary: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

              dataSource: Person[] = [
                {
                  name: 'Tiger Nixon',
                  position: 'System Architect',
                  office: 'Edinburgh',
                  age: 61,
                  startDate: '2011/04/25',
                  salary: '$320,800',
                },
                {
                  name: 'Sonya Frost',
                  position: 'Software Engineer',
                  office: 'Edinburgh',
                  age: 23,
                  startDate: '2008/12/13',
                  salary: '$103,600',
                },
                {
                  name: 'Jena Gaines',
                  position: 'Office Manager',
                  office: 'London',
                  age: 30,
                  startDate: '2008/12/19',
                  salary: '$90,560',
                },
                {
                  name: 'Quinn Flynn',
                  position: 'Support Lead',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2013/03/03',
                  salary: '$342,000',
                },
                {
                  name: 'Charde Marshall',
                  position: 'Regional Director',
                  office: 'San Francisco',
                  age: 36,
                  startDate: '2008/10/16',
                  salary: '$470,600',
                },
                {
                  name: 'Haley Kennedy',
                  position: 'Senior Marketing Designer',
                  office: 'London',
                  age: 43,
                  startDate: '2012/12/18',
                  salary: '$313,500',
                },
                {
                  name: 'Tatyana Fitzpatrick',
                  position: 'Regional Director',
                  office: 'London',
                  age: 19,
                  startDate: '2010/03/17',
                  salary: '$385,750',
                },
                {
                  name: 'Michael Silva',
                  position: 'Marketing Designer',
                  office: 'London',
                  age: 66,
                  startDate: '2012/11/27',
                  salary: '$198,500',
                },
                {
                  name: 'Paul Byrd',
                  position: 'Chief Financial Officer (CFO)',
                  office: 'New York',
                  age: 64,
                  startDate: '2010/06/09',
                  salary: '$725,000',
                },
                {
                  name: 'Gloria Little',
                  position: 'Systems Administrator',
                  office: 'New York',
                  age: 59,
                  startDate: '2009/04/10',
                  salary: '$237,500',
                },
                {
                  name: 'Garrett Winters',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 63,
                  startDate: '2011/07/25',
                  salary: '$170,750',
                },
                {
                  name: 'Ashton Cox',
                  position: 'Junior Technical Author',
                  office: 'San Francisco',
                  age: 66,
                  startDate: '2009/01/12',
                  salary: '$86,000',
                },
                {
                  name: 'Cedric Kelly',
                  position: 'Senior Javascript Developer',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2012/03/29',
                  salary: '$433,060',
                },
                {
                  name: 'Airi Satou',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 33,
                  startDate: '2008/11/28',
                  salary: '$162,700',
                },
                {
                  name: 'Brielle Williamson',
                  position: 'Integration Specialist',
                  office: 'New York',
                  age: 61,
                  startDate: '2012/12/02',
                  salary: '$372,000',
                },
              ];
            }
          
        
    

Async data

Loading content asynchronously is an important part of working with data tables - with MDB Datatable you can easily display content after fetching it from API.

        
            
            <div class="datatable mt-4">
              <div class="datatable-inner" mdbScrollbar style="position: relative">
                <table
                  class="table datatable-table"
                  mdbTable
                  mdbTableSort
                  #table="mdbTable"
                  #sort="mdbTableSort"
                  [dataSource]="dataSource$ | async"
                  [pagination]="pagination"
                  [sort]="sort"
                >
                  <thead class="datatable-header">
                    <tr>
                      <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                        {{ header | titlecase }}
                      </th>
                    </tr>
                  </thead>
                  <tbody class="datatable-body" *ngIf="!loading">
                    <tr *ngFor="let data of table.data" scope="row">
                      <td>
                        {{ data.email }}
                      </td>
                      <td>
                        {{ data.name }}
                      </td>
                      <td>
                        {{ data.phone }}
                      </td>
                      <td>
                        {{ data.username }}
                      </td>
                      <td>
                        {{ data.website }}
                      </td>
                      <td>{{ data.address.city }}, {{ data.address.street }}</td>
                      <td>
                        {{ data.company.name }}
                      </td>
                    </tr>
                  </tbody>
                </table>
                <ng-container *ngIf="loading">
                  <div class="datatable-loader bg-light">
                    <span class="datatable-loader-inner">
                      <span class="datatable-progress bg-primary"></span>
                    </span>
                  </div>
                  <p class="text-center text-muted my-4">Loading results...</p>
                </ng-container>
              </div>
              <mdb-table-pagination #pagination></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component, OnInit } from '@angular/core';
            import { Observable } from 'rxjs';
            import { HttpClient } from '@angular/common/http';
            import { delay, tap } from 'rxjs/operators';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              startDate: string;
              salary: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent implements OnInit {
              dataUrl = 'https://jsonplaceholder.typicode.com/users';
              dataSource$: Observable<any[]>;
              loading = true;

              constructor(private _http: HttpClient) {}

              ngOnInit(): void {
                this.dataSource$ = this._http.get<any>(this.dataUrl).pipe(
                  delay(7000),
                  tap(() => (this.loading = false))
                );
              }

              headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

              reloadData(): void {
                this.loading = true;
                this.dataSource$ = this._http.get<any>(this.dataUrl).pipe(
                  delay(7000),
                  tap(() => (this.loading = false))
                );
              }
            }
          
        
    

Action buttons

With the Datatable it's possible to render custom content, such as action buttons and attach listeners to their events.

        
            
            <div class="datatable mt-4">
              <table
                class="table datatable-table"
                mdbTable
                mdbTableSort
                #table="mdbTable"
                #sort="mdbTableSort"
                [dataSource]="dataSource"
                [hover]="true"
                [sort]="sort"
                [pagination]="pagination"
              >
                <thead class="datatable-header">
                  <tr>
                    <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                      {{ header | titlecase }}
                    </th>
                  </tr>
                </thead>
                <tbody class="datatable-body">
                  <tr
                    *ngFor="let data of table.data"
                    scope="row"
                  >
                    <td>
                      {{ data.name }}
                    </td>
                    <td>
                      {{ data.position }}
                    </td>
                    <td>
                      {{ data.office }}
                    </td>
                    <td>
                      <button
                        class="call-btn btn btn-outline-primary btn-floating btn-sm"
                        (click)="logData(data.phone)">
                        <i class="fa fa-phone"></i>
                      </button>
                      <button
                        class="messhandle-btn btn ms-2 btn-primary btn-floating btn-sm"
                        (click)="logData(data.email)">
                        <i class="fa fa-envelope"></i>
                      </button>
                    </td>
                  </tr>
                </tbody>
              </table>
              <mdb-table-pagination #pagination></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component } from '@angular/core';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              phone: string;
              email: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              headers = ['Name', 'Position', 'Office'];

              dataSource: Person[] = [
                {
                  name: 'Tiger Nixon',
                  position: 'System Architect',
                  office: 'Edinburgh',
                  phone: '+48000000000',
                  email: 'tiger.nixon@gmail.com'
                },
                {
                  name: 'Sonya Frost',
                  position: 'Software Engineer',
                  office: 'Edinburgh',
                  phone: '+53456123456',
                  email: 'sfrost@gmail.com'
                },
                {
                  name: 'Tatyana Fitzpatrick',
                  position: 'Regional Director',
                  office: 'London',
                  phone: '+42123432456',
                  email: 'tfitz@gmail.com'
                }
              ];

              logData(data: string): void {
                console.log(data)
              }
            }
          
        
    

Cell formatting

Use [ngStyle] attribute directive to implement cell formatting to color individual cells.

        
            
            <div class="datatable mt-4">
              <table
                class="table datatable-table"
                mdbTable
                mdbTableSort
                #table="mdbTable"
                #sort="mdbTableSort"
                [dataSource]="dataSource"
                [pagination]="pagination"
                [sort]="sort"
              >
                <thead class="datatable-header">
                  <tr>
                    <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                      {{ header | titlecase }}
                    </th>
                  </tr>
                </thead>
                <tbody class="datatable-body">
                  <tr *ngFor="let data of table.data" scope="row">
                    <td>
                      {{ data.product }}
                    </td>
                    <td>
                      {{ data.quantity }}
                    </td>
                    <td [ngStyle]="formatCell(data.purchases)">
                      {{ data.purchases }}
                    </td>
                  </tr>
                </tbody>
              </table>
              <mdb-table-pagination #pagination></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component } from '@angular/core';

            export interface Product {
              product: string;
              quantity: number;
              purchases: number;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              headers = ['Product', 'Quantity', 'Purchases'];

              dataSource: Product[] = [
              { product: 'Product 1', quantity: 10, purchases: 103 },
              { product: 'Product 2', quantity: 45, purchases: 110 },
              { product: 'Product 3', quantity: 76, purchases: 56 },
              { product: 'Product 4', quantity: 89, purchases: 230 },
              { product: 'Product 5', quantity: 104, purchases: 240 },
              { product: 'Product 6', quantity: 97, purchases: 187 },
              { product: 'Product 7', quantity: 167, purchases: 130 },
              { product: 'Product 8', quantity: 50, purchases: 199 },
              { product: 'Product 9', quantity: 4, purchases: 206 },
              { product: 'Product 10', quantity: 120, purchases: 88 },
              { product: 'Product 11', quantity: 22, purchases: 100 },
            ];

            colors = ['#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5'];
            maxValue = Math.max(...this.dataSourceCellFormatting.map((data) => data.purchases));
            minValue = Math.min(...this.dataSourceCellFormatting.map((data) => data.purchases));
            step = (this.maxValue - this.minValue) / (this.colors.length - 1);
          
            formatCell(value: number): { 'background-color': string; 'font-weight': number } {
              const colorIndex = Math.floor((value - this.minValue) / this.step);
              const backgroundColor = this.colors[colorIndex];
              const fontWeight = 400;
          
              return {
                'background-color': backgroundColor,
                'font-weight': fontWeight,
              };
            }
            }
          
        
    

Clickable rows

Click on the row to preview the message.

Selecting the row with checkbox doesn't trigger rowClick event.

Note: To prevent this action with other clickable elements within the row, call stopPropagation() method.

Note: This feature cannot be used simultaneously with edit option.

        
            
            <div class="datatable mt-4">
              <table
                class="table datatable-table"
                mdbTable
                mdbTableSort
                #table="mdbTable"
                #sort="mdbTableSort"
                [dataSource]="dataSource"
                [sort]="sort"
                [pagination]="pagination"
              >
                <thead class="datatable-header">
                  <tr>
                    <th scope="col">
                      <div class="form-check d-flex align-items-center mb-0">
                        <input
                          mdbCheckbox
                          class="datatable-header-checkbox form-check-input"
                          type="checkbox"
                          [checked]="allRowsSelected()"
                          (checkboxChange)="toggleAll($event)"
                        />
                      </div>
                    </th>
                    <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                      {{ header | titlecase }}
                    </th>
                  </tr>
                </thead>
                <tbody class="datatable-body">
                  <tr
                    *ngFor="let data of table.data"
                    scope="row"
                    (click)="onRowClick()"
                    [class.active]="selections.has(data)"
                    style="cursor: pointer;"
                  >
                    <td>
                      <div class="form-check">
                        <input
                          mdbCheckbox
                          (click)="$event.stopPropagation()"
                          (checkboxChange)="toggleSelection($event, data)"
                          [checked]="selections.has(data)"
                          class="datatable-row-checkbox form-check-input"
                          type="checkbox"
                        />
                      </div>
                    </td>
                    <td>
                      {{ data.name }}
                    </td>
                    <td>
                      {{ data.position }}
                    </td>
                    <td>
                      {{ data.office }}
                    </td>
                    <td>
                      {{ data.age }}
                    </td>
                    <td>
                      {{ data.startDate }}
                    </td>
                    <td>
                      {{ data.salary }}
                    </td>
                    <td>
                      <button
                        class="call-btn btn btn-outline-primary btn-floating btn-sm"
                        (click)="$event.stopPropagation()"
                      >
                        <i class="fa fa-phone"></i>
                      </button>
                      <button
                        class="messhandle-btn btn ms-2 btn-primary btn-floating btn-sm"
                        (click)="$event.stopPropagation()"
                      >
                        <i class="fa fa-envelope"></i>
                      </button>
                    </td>
                  </tr>
                </tbody>
              </table>
              <mdb-table-pagination #pagination></mdb-table-pagination>
            </div>
          
        
    
        
            
            import { Component } from '@angular/core';
            import { MdbCheckboxChange } from 'mdb-angular-ui-kit/checkbox';

            export interface Person {
              name: string;
              position: string;
              office: string;
              age: number;
              startDate: string;
              salary: string;
            }

            @Component({
              selector: 'app-root',
              templateUrl: './app.component.html',
            })
            export class AppComponent {
              constructor() {}

              selections = new Set<Person>();

              headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

              dataSource: Person[] = [
                {
                  name: 'Tiger Nixon',
                  position: 'System Architect',
                  office: 'Edinburgh',
                  age: 61,
                  startDate: '2011/04/25',
                  salary: '$320,800',
                },
                {
                  name: 'Sonya Frost',
                  position: 'Software Engineer',
                  office: 'Edinburgh',
                  age: 23,
                  startDate: '2008/12/13',
                  salary: '$103,600',
                },
                {
                  name: 'Jena Gaines',
                  position: 'Office Manager',
                  office: 'London',
                  age: 30,
                  startDate: '2008/12/19',
                  salary: '$90,560',
                },
                {
                  name: 'Quinn Flynn',
                  position: 'Support Lead',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2013/03/03',
                  salary: '$342,000',
                },
                {
                  name: 'Charde Marshall',
                  position: 'Regional Director',
                  office: 'San Francisco',
                  age: 36,
                  startDate: '2008/10/16',
                  salary: '$470,600',
                },
                {
                  name: 'Haley Kennedy',
                  position: 'Senior Marketing Designer',
                  office: 'London',
                  age: 43,
                  startDate: '2012/12/18',
                  salary: '$313,500',
                },
                {
                  name: 'Tatyana Fitzpatrick',
                  position: 'Regional Director',
                  office: 'London',
                  age: 19,
                  startDate: '2010/03/17',
                  salary: '$385,750',
                },
                {
                  name: 'Michael Silva',
                  position: 'Marketing Designer',
                  office: 'London',
                  age: 66,
                  startDate: '2012/11/27',
                  salary: '$198,500',
                },
                {
                  name: 'Paul Byrd',
                  position: 'Chief Financial Officer (CFO)',
                  office: 'New York',
                  age: 64,
                  startDate: '2010/06/09',
                  salary: '$725,000',
                },
                {
                  name: 'Gloria Little',
                  position: 'Systems Administrator',
                  office: 'New York',
                  age: 59,
                  startDate: '2009/04/10',
                  salary: '$237,500',
                },
                {
                  name: 'Garrett Winters',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 63,
                  startDate: '2011/07/25',
                  salary: '$170,750',
                },
                {
                  name: 'Ashton Cox',
                  position: 'Junior Technical Author',
                  office: 'San Francisco',
                  age: 66,
                  startDate: '2009/01/12',
                  salary: '$86,000',
                },
                {
                  name: 'Cedric Kelly',
                  position: 'Senior Javascript Developer',
                  office: 'Edinburgh',
                  age: 22,
                  startDate: '2012/03/29',
                  salary: '$433,060',
                },
                {
                  name: 'Airi Satou',
                  position: 'Accountant',
                  office: 'Tokyo',
                  age: 33,
                  startDate: '2008/11/28',
                  salary: '$162,700',
                },
                {
                  name: 'Brielle Williamson',
                  position: 'Integration Specialist',
                  office: 'New York',
                  age: 61,
                  startDate: '2012/12/02',
                  salary: '$372,000',
                },
              ];

              onRowClick(): void {
                alert('row clicked');
              }

              allRowsSelected(): boolean {
                const selectionsLength = this.selections.size;
                const dataLength = this.dataSource.length;
                return selectionsLength === dataLength;
              }

              toggleSelection(event: MdbCheckboxChange, value: Person): void {
                if (event.checked) {
                  this.select(value);
                } else {
                  this.deselect(value);
                }
              }

              toggleAll(event: MdbCheckboxChange): void {
                if (event.checked) {
                  this.dataSource.forEach((row: Person) => {
                    this.select(row);
                  });
                } else {
                  this.dataSource.forEach((row: Person) => {
                    this.deselect(row);
                  });
                }
              }

              select(value: Person): void {
                if (!this.selections.has(value)) {
                  this.selections.add(value);
                }
              }

              deselect(value: Person): void {
                if (this.selections.has(value)) {
                  this.selections.delete(value);
                }
              }
            }
          
        
    

Datatables - API


Import

        
            
          import { MdbTableModule } from 'mdb-angular-ui-kit/table';
          …
          @NgModule ({
            ...
            imports: [MdbTableModule],
            ...
          })
        
        
    

Inputs

MdbTableDirective

Name Type Default Description
bordered Boolean false Adds borders to a datatable
borderless Boolean false Removes all borders from a datatable
dataSource T[] [] Changes table data source array
fixedHeader Boolean false When it's set to true, the table's header will remain visible while scrolling
filterFn (data: T, searchTerm: string) => boolean - Changes function used for data search
hover Boolean false Changes the background color of a hovered row
pagination MdbTablePaginationComponent - Changes attached table pagination component
sort MdbTableSortDirective - Changes attached table sort directive
sm Boolean false Decreases a row's paddings
striped Boolean false Slightly changes the background's color in every other row

MdbTableSortHeaderDirective

Name Type Default Description
disableSort boolean false Disables sorting for chosen column
forceSort boolean false When it's set to true, the table's sort will toggle between two options: ascending and descending. The initial state will not be one of the options.
mdbTableSortHeader string '' Changes name of the sort header

MdbTablePaginationComponent

Name Type Default Description
allText string 'All' Defines text for 'All' option
disabled boolean false Whether pagination should be disabled
entries number 10 Changes number of displayed entries
entriesOptions Array [10, 25, 50, 200] Options available to choose from in a pagination select (rows per page)
nextButtonDisabled boolean false Whether next button should be disabled
page number 0 Sets current page
prevButtonDisabled boolean false Whether previous button should be disabled
rowsPerPageText string Rows per page Changes 'Rows per page' text value
ofText string of Changes 'of' text value
showAllEntries boolean false Defines whether 'All' option is available
total number 0 Changes number of total pagination entries

Outputs

MdbTableSortDirective

Name Type Description
sortChange EventEmitter<MdbSortChange> Event fired on data sort change

MdbTablePaginationComponent

Name Type Description
paginationChange EventEmitter<MdbPaginationChange> Event fired on pagination change
        
            
              <div class="datatable mt-4">
                <table
                  class="table datatable-table"
                  mdbTable
                  mdbTableSort
                  #table="mdbTable"
                  #sort="mdbTableSort"
                  [dataSource]="dataSource"
                  [pagination]="pagination"
                  [sort]="sort"
                  (sortChange)="onSortChange($event)"
                >
                  <thead class="datatable-header">
                    <tr>
                      <th *ngFor="let header of headers" [mdbTableSortHeader]="header" scope="col">
                        {{ header | titlecase }}
                      </th>
                    </tr>
                  </thead>
                  <tbody class="datatable-body">
                    <tr *ngFor="let data of table.data" scope="row">
                      <td>
                        {{ data.name }}
                      </td>
                      <td>
                        {{ data.position }}
                      </td>
                      <td>
                        {{ data.office }}
                      </td>
                      <td>
                        {{ data.age }}
                      </td>
                      <td>
                        {{ data.startDate }}
                      </td>
                      <td>
                        {{ data.salary }}
                      </td>
                    </tr>
                  </tbody>
                </table>
                <mdb-table-pagination #pagination (paginationChange)="onPaginationChange($event)"></mdb-table-pagination>
              </div>
            
        
    
        
            
              import { Component } from '@angular/core';
              import { MdbSortChange, MdbPaginationChange } from 'mdb-angular-ui-kit/table';

              export interface Person {
                name: string;
                position: string;
                office: string;
                age: number;
                startDate: string;
                salary: string;
              }

              @Component({ selector: 'app-datatable',
                templateUrl: './datatable.component.html',
                styleUrls: ['./datatable.component.scss'],
              })
              export class DatatableComponent {
                headers = ['Name', 'Position', 'Office', 'Age', 'Start Date', 'Salary'];

                dataSource: Person[] = [
                  {
                    name: 'Tiger Nixon',
                    position: 'System Architect',
                    office: 'Edinburgh',
                    age: 61,
                    startDate: '2011/04/25',
                    salary: '$320,800',
                  },
                  {
                    name: 'Sonya Frost',
                    position: 'Software Engineer',
                    office: 'Edinburgh',
                    age: 23,
                    startDate: '2008/12/13',
                    salary: '$103,600',
                  },
                  {
                    name: 'Jena Gaines',
                    position: 'Office Manager',
                    office: 'London',
                    age: 30,
                    startDate: '2008/12/19',
                    salary: '$90,560',
                  },
                  {
                    name: 'Quinn Flynn',
                    position: 'Support Lead',
                    office: 'Edinburgh',
                    age: 22,
                    startDate: '2013/03/03',
                    salary: '$342,000',
                  },
                  {
                    name: 'Charde Marshall',
                    position: 'Regional Director',
                    office: 'San Francisco',
                    age: 36,
                    startDate: '2008/10/16',
                    salary: '$470,600',
                  },
                  {
                    name: 'Haley Kennedy',
                    position: 'Senior Marketing Designer',
                    office: 'London',
                    age: 43,
                    startDate: '2012/12/18',
                    salary: '$313,500',
                  },
                  {
                    name: 'Tatyana Fitzpatrick',
                    position: 'Regional Director',
                    office: 'London',
                    age: 19,
                    startDate: '2010/03/17',
                    salary: '$385,750',
                  },
                  {
                    name: 'Michael Silva',
                    position: 'Marketing Designer',
                    office: 'London',
                    age: 66,
                    startDate: '2012/11/27',
                    salary: '$198,500',
                  },
                  {
                    name: 'Paul Byrd',
                    position: 'Chief Financial Officer (CFO)',
                    office: 'New York',
                    age: 64,
                    startDate: '2010/06/09',
                    salary: '$725,000',
                  },
                  {
                    name: 'Gloria Little',
                    position: 'Systems Administrator',
                    office: 'New York',
                    age: 59,
                    startDate: '2009/04/10',
                    salary: '$237,500',
                  },
                  {
                    name: 'Garrett Winters',
                    position: 'Accountant',
                    office: 'Tokyo',
                    age: 63,
                    startDate: '2011/07/25',
                    salary: '$170,750',
                  },
                  {
                    name: 'Ashton Cox',
                    position: 'Junior Technical Author',
                    office: 'San Francisco',
                    age: 66,
                    startDate: '2009/01/12',
                    salary: '$86,000',
                  },
                  {
                    name: 'Cedric Kelly',
                    position: 'Senior Javascript Developer',
                    office: 'Edinburgh',
                    age: 22,
                    startDate: '2012/03/29',
                    salary: '$433,060',
                  },
                  {
                    name: 'Airi Satou',
                    position: 'Accountant',
                    office: 'Tokyo',
                    age: 33,
                    startDate: '2008/11/28',
                    salary: '$162,700',
                  },
                  {
                    name: 'Brielle Williamson',
                    position: 'Integration Specialist',
                    office: 'New York',
                    age: 61,
                    startDate: '2012/12/02',
                    salary: '$372,000',
                  },
                ];

                constructor() {}

                onSortChange(event: MdbSortChange): void {
                  console.log('sort change event', event);
                }

                onPaginationChange(event: MdbPaginationChange): void {
                  console.log('pagination change event', event);
                }
              }
            
        
    

Advanced types

MdbPaginationChange

        
            
            interface MdbPaginationChange {
              page: number;
              entries: number;
              total: number;
            }
            
        
    

MdbSortChange

        
            
            interface MdbSortChange {
              name: string;
              direction: MdbSortDirection;
            }
            
        
    

MdbSortDirection

        
            
            type MdbSortDirection = 'asc' | 'desc' | 'none';