Table editor

Angular Bootstrap 5 Table editor plugin

Table Editor is a useful tool for displaying and managing data. The component works similarly to the Datatable (docs) with an additional column for action buttons.

Responsive interactive built with Bootstrap 5, Angular and Material Design. Creates editable tables. Delete or edit rows directly or via modal editor.

Note: Examples use additional components such as Datatables, Modal, Alerts and Popconfirm. Remember to import them.


Basic example


Company Address Employees Actions
Smith & JohnsonPark Lane 2, London30
P.J. CompanyOak Street 7, Aberdeen80
Food & WineNetherhall Gardens 3, Hampstead12
IT ServiceWarwick Road 14, London17
A. Jonson GalleryOaklands Avenue 2, London4

Rows per page:

5
1 - 5 of 6
<div class="d-flex justify-content-end mb-4">
  <mdb-form-control>
    <input
      mdbInput
      type="text"
      class="form-control"
      id="search-input"
      [disabled]="addRow || editElementIndex !== -1"
      (keyup)="search($event)"
    />
    <label mdbLabel class="form-label" for="search-input">Search</label>
  </mdb-form-control>
  <button
    mdbRipple
    class="btn btn-primary btn-sm ms-3"
    [disabled]="addRow || editElementIndex !== -1"
    (click)="addRow = true"
  >
    <i class="fa fa-plus"></i>
  </button>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{ 'edited-table': addRow || editElementIndex !== -1 }"
>
  <table
    class="table datatable-table"
    mdbTable
    mdbTableSort
    #table="mdbTable"
    #sort="mdbTableSort"
    [dataSource]="dataSource"
    [sort]="sort"
    [pagination]="pagination"
  >
    <thead class="datatable-header">
      <tr>
        <th
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr
        *ngIf="addRow"
        [ngClass]="{ 'edited-row': addRow }"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.address"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="number"
              class="form-control"
              [(ngModel)]="newRow.employees"
            />
          </mdb-form-control>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{ 'edited-row': editElementIndex === index }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.address }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.address"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.employees }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="number"
                class="form-control"
                [(ngModel)]="data.employees"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="onEditClick(index)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              (click)="onDeleteClick(data)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="onDiscardEdit(index)"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </td>
      </tr>
    </tbody>
  </table>
  <mdb-table-pagination
    #pagination
    [entries]="5"
    [disabled]="addRow || editElementIndex !== -1"
  ></mdb-table-pagination>
</div>
import { Component, ViewChild } from '@angular/core';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';

export interface Person {
  company: string;
  address: string;
  employees: number | null;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  editElementIndex = -1;
  addRow = false;

  newRow: Person = {
    company: '',
    address: '',
    employees: null,
  };

  editRow: Person = {
    company: '',
    address: '',
    employees: null,
  };

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Address', field: 'address', disableSort: true },
    { label: 'Employees', field: 'employees', disableSort: true },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      address: 'Park Lane 2, London',
      employees: 30,
    },
    {
      company: 'P.J. Company',
      address: 'Oak Street 7, Aberdeen',
      employees: 80,
    },
    {
      company: 'Food & Wine',
      address: 'Netherhall Gardens 3, Hampstead',
      employees: 12,
    },
    {
      company: 'IT Service',
      address: 'Warwick Road 14, London',
      employees: 17,
    },
    {
      company: 'A. Jonson Gallery',
      address: 'Oaklands Avenue 2, London',
      employees: 4,
    },
    {
      company: 'F.A. Architects',
      address: 'Frognal Way 7, Hampsteadn',
      employees: 4,
    },
  ];

  constructor() {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow(): void {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.newRow.company = '';
    this.newRow.address = '';
    this.newRow.employees = null;
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.address = '';
    this.newRow.employees = null;
    this.addRow = false;
  }

  onEditClick(index: number): void {
    this.editElementIndex = index;
    this.editRow = { ...this.table.data[index] };
  }

  onDiscardEdit(index: number): void {
    this.editElementIndex = -1;
    this.table.data[index] = { ...this.editRow };
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }
}

Modal

Note: This example use Modal. Remember to import them.


Company Office Employees International Actions
Smith & JohnsonLondon30true
P.J. CompanyLondon80false
Food & WineLondon12false
IT ServiceLondon17false
A. Jonson GalleryLondon4false

Rows per page:

5
1 - 5 of 6
<div class="d-flex justify-content-end mb-4">
  <mdb-form-control>
    <input
      mdbInput
      type="text"
      class="form-control"
      id="search-input"
      (keyup)="search($event)"
    />
    <label mdbLabel class="form-label" for="search-input">Search</label>
  </mdb-form-control>
  <button
    mdbRipple
    class="btn btn-primary btn-sm ms-3"
    (click)="openModal('add')"
  >
    <i class="fa fa-plus"></i>
  </button>
</div>
<hr />
<div class="datatable table-editor 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
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr *ngFor="let data of table.data; let index = index" scope="row">
        <td style="min-width: 250px; max-width: 250px">
          {{ data.company }}
        </td>
        <td style="min-width: 250px; max-width: 250px">
          {{ data.office }}
        </td>
        <td style="min-width: 250px; max-width: 250px">
          {{ data.employees }}
        </td>
        <td style="min-width: 100px; max-width: 100px">
          {{ data.international }}
        </td>

        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
            (click)="openModal('edit', data)"
          >
            <i class="far fa-edit"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
            (click)="onDeleteClick(data)"
          >
            <i class="far fa-trash-alt"></i>
          </button>
        </td>
      </tr>
    </tbody>
  </table>
  <mdb-table-pagination #pagination [entries]="5"></mdb-table-pagination>
</div>
import { Component, ViewChild } from '@angular/core';
import { MdbModalRef, MdbModalService } from 'mdb-angular-ui-kit/modal';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';
import { ModalComponent } from './modal.component';

export interface Person {
  company: string;
  office: string;
  employees: number | null;
  international: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  modalRef: MdbModalRef<ModalComponent> | null = null;

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Office', field: 'office', disableSort: true },
    { label: 'Employees', field: 'employees', disableSort: false },
    { label: 'International', field: 'international', disableSort: false },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      office: 'London',
      employees: 30,
      international: true,
    },
    {
      company: 'P.J. Company',
      office: 'London',
      employees: 80,
      international: false,
    },
    {
      company: 'Food & Wine',
      office: 'London',
      employees: 12,
      international: false,
    },
    {
      company: 'IT Service',
      office: 'London',
      employees: 17,
      international: false,
    },
    {
      company: 'A. Jonson Gallery',
      office: 'London',
      employees: 4,
      international: false,
    },
    {
      company: 'F.A. Architects',
      office: 'London',
      employees: 4,
      international: false,
    },
  ];

  constructor(private modalService: MdbModalService) {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  openModal(mode: 'add' | 'edit', data?: Person): void {
    this.modalRef = this.modalService.open(ModalComponent, {
      data: {
        modalTitle: mode === 'edit' ? 'Edit item' : 'New item',
        company: data ? data.company : '',
        office: data ? data.office : 'Warsaw',
        employees: data ? data.employees : 1,
        international: data ? data.international : false,
      },
      ignoreBackdropClick: true,
    });
    this.modalRef.onClose.subscribe((modalData: Person) => {
      if (!modalData) {
        return;
      }
      if (mode === 'add') {
        this.dataSource = [...this.dataSource, { ...modalData }];
      } else if (mode === 'edit' && data) {
        const index = this.dataSource.indexOf(data);
        this.dataSource[index] = modalData;
        this.dataSource = [...this.dataSource];
      }
    });
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }
}
<div class="modal-header">
  <h5 class="modal-title" id="exampleModalLabel">{{ modalTitle }}</h5>
</div>
<div class="modal-body">
  <div class="my-4 table-editor_input-wrapper">
    <mdb-form-control>
      <input
        mdbInput
        type="text"
        id="company-input"
        class="form-control"
        [(ngModel)]="company"
      />
      <label mdbLabel class="form-label" for="company-input">Company</label>
    </mdb-form-control>
  </div>
  <div class="my-4 table-editor_input-wrapper">
    <mdb-form-control>
      <mdb-select [(ngModel)]="office">
        <mdb-option *ngFor="let option of options" [value]="option.value">{{
          option.label
        }}</mdb-option>
      </mdb-select>
      <label mdbLabel class="form-label">Office</label>
    </mdb-form-control>
  </div>
  <div class="my-4 table-editor_input-wrapper">
    <mdb-form-control>
      <input
        mdbInput
        type="number"
        id="employees-input"
        class="form-control"
        [(ngModel)]="employees"
      />
      <label mdbLabel class="form-label" for="employees-input">Employees</label>
    </mdb-form-control>
  </div>
  <div class="my-4 table-editor_input-wrapper">
    <div class="form-check ms-1 mt-1">
      <input
        mdbCheckbox
        class="form-check-input"
        type="checkbox"
        value=""
        id="international-checkbox"
        [(ngModel)]="international"
      />
      <label class="form-check-label" for="flexCheckDefault">
        International
      </label>
    </div>
  </div>
</div>
<div class="modal-footer">
  <button
    type="button"
    class="shadow-0 btn btn-md btn-outline-primary"
    (click)="modalRef.close()"
  >
    Cancel
  </button>
  <button
    type="button"
    class="shadow-0 btn btn-md btn-primary"
    (click)="saveData()"
  >
    Save
  </button>
</div>
import { Component } from '@angular/core';
import { MdbModalRef } from 'mdb-angular-ui-kit/modal';

@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html',
})
export class ModalComponent {
  modalTitle: string | null = null;
  company: string | null = null;
  office: string | null = null;
  employees: string | null = null;
  international: string | null = null;

  options = [
    { value: 'London', label: 'London' },
    { value: 'Warsaw', label: 'Warsaw' },
    { value: 'New York', label: 'New York' },
  ];

  constructor(public modalRef: MdbModalRef<ModalComponent>) {}

  saveData(): void {
    const closeMessage = {
      company: this.company,
      office: this.office,
      employees: this.employees,
      international: this.international,
    };

    this.modalRef.close(closeMessage);
  }
}

Inputs example


Company Office Employees International Actions
Smith & JohnsonLondon30true
P.J. CompanyLondon80false
Food & WineLondon12false
IT ServiceLondon17false
A. Jonson GalleryLondon4false

Rows per page:

5
1 - 5 of 6
<div class="d-flex justify-content-end mb-4">
  <mdb-form-control>
    <input
      mdbInput
      type="text"
      class="form-control"
      id="search-input"
      [disabled]="addRow || editElementIndex !== -1"
      (keyup)="search($event)"
    />
    <label mdbLabel class="form-label" for="search-input">Search</label>
  </mdb-form-control>
  <button
    mdbRipple
    class="btn btn-primary btn-sm ms-3"
    [disabled]="addRow || editElementIndex !== -1"
    (click)="addRow = true"
  >
    <i class="fa fa-plus"></i>
  </button>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{
    'edited-table': addRow || editElementIndex !== -1
  }"
>
  <table
    class="table datatable-table"
    mdbTable
    mdbTableSort
    #table="mdbTable"
    #sort="mdbTableSort"
    [dataSource]="dataSource"
    [sort]="sort"
    [pagination]="pagination"
  >
    <thead class="datatable-header">
      <tr>
        <th
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr
        *ngIf="addRow"
        [ngClass]="{ 'edited-row': addRow }"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <mdb-select [(ngModel)]="newRow.office">
              <mdb-option
                *ngFor="let option of options"
                [value]="option.value"
                >{{ option.label }}</mdb-option
              >
            </mdb-select>
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="number"
              class="form-control"
              [(ngModel)]="newRow.employees"
            />
          </mdb-form-control>
        </td>
        <td>
          <div class="form-check ms-1 mt-1">
            <input
              mdbCheckbox
              class="form-check-input"
              type="checkbox"
              [(ngModel)]="newRow.international"
            />
          </div>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{ 'edited-row': editElementIndex === index }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.office }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <mdb-select [(ngModel)]="data.office">
                <mdb-option
                  *ngFor="let option of options"
                  [value]="option.value"
                  >{{ option.label }}</mdb-option
                >
              </mdb-select>
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.employees }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="number"
                class="form-control"
                [(ngModel)]="data.employees"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.international }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <div class="form-check ms-1 mt-1">
              <input
                mdbCheckbox
                class="form-check-input"
                type="checkbox"
                [(ngModel)]="data.international"
              />
            </div>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="onEditClick(index)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              (click)="onDeleteClick(data)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="onDiscardEdit(index)"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </td>
      </tr>
    </tbody>
  </table>
  <mdb-table-pagination
    #pagination
    [entries]="5"
    [disabled]="addRow || editElementIndex !== -1"
  ></mdb-table-pagination>
</div>
import { Component, ViewChild } from '@angular/core';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';

export interface Person {
  company: string;
  office: string;
  employees: number | null;
  international: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  editElementIndex = -1;
  addRow = false;

  newRow: Person = {
    company: '',
    office: 'Warsaw',
    employees: 1,
    international: false,
  };

  editRow: Person = {
    company: '',
    office: '',
    employees: null,
    international: false,
  };

  options = [
    { value: 'London', label: 'London' },
    { value: 'Warsaw', label: 'Warsaw' },
    { value: 'New York', label: 'New York' },
  ];

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Office', field: 'office', disableSort: true },
    { label: 'Employees', field: 'employees', disableSort: false },
    { label: 'International', field: 'international', disableSort: false },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      office: 'London',
      employees: 30,
      international: true,
    },
    {
      company: 'P.J. Company',
      office: 'London',
      employees: 80,
      international: false,
    },
    {
      company: 'Food & Wine',
      office: 'London',
      employees: 12,
      international: false,
    },
    {
      company: 'IT Service',
      office: 'London',
      employees: 17,
      international: false,
    },
    {
      company: 'A. Jonson Gallery',
      office: 'London',
      employees: 4,
      international: false,
    },
    {
      company: 'F.A. Architects',
      office: 'London',
      employees: 4,
      international: false,
    },
  ];

  constructor() {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow(): void {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  onEditClick(index: number): void {
    this.editElementIndex = index;
    this.editRow = { ...this.table.data[index] };
  }

  onDiscardEdit(index: number): void {
    this.editElementIndex = -1;
    this.table.data[index] = { ...this.editRow };
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }
}

Disable edit


Company Office Employees International Actions
Smith & JohnsonLondon30true
P.J. CompanyLondon80false
Food & WineLondon12false
IT ServiceLondon17false
A. Jonson GalleryLondon4false

Rows per page:

5
1 - 5 of 6
<div class="d-flex justify-content-end mb-4">
  <mdb-form-control>
    <input
      mdbInput
      type="text"
      class="form-control"
      id="search-input"
      [disabled]="addRow || editElementIndex !== -1"
      (keyup)="search($event)"
    />
    <label mdbLabel class="form-label" for="search-input">Search</label>
  </mdb-form-control>
  <button
    mdbRipple
    class="btn btn-primary btn-sm ms-3"
    [disabled]="addRow || editElementIndex !== -1"
    (click)="addRow = true"
  >
    <i class="fa fa-plus"></i>
  </button>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{
    'edited-table': addRow || editElementIndex !== -1
  }"
>
  <table
    class="table datatable-table"
    mdbTable
    mdbTableSort
    #table="mdbTable"
    #sort="mdbTableSort"
    [dataSource]="dataSource"
    [sort]="sort"
    [pagination]="pagination"
  >
    <thead class="datatable-header">
      <tr>
        <th
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr
        *ngIf="addRow"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
        [ngClass]="{ 'edited-row': addRow }"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
              disabled
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <mdb-select [(ngModel)]="newRow.office" disabled>
              <mdb-option
                *ngFor="let option of options"
                [value]="option.value"
                >{{ option.label }}</mdb-option
              >
            </mdb-select>
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="number"
              class="form-control"
              [(ngModel)]="newRow.employees"
              disabled
            />
          </mdb-form-control>
        </td>
        <td>
          <div class="form-check ms-1 mt-1">
            <input
              mdbCheckbox
              class="form-check-input"
              type="checkbox"
              [(ngModel)]="newRow.international"
              disabled
            />
          </div>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{
          'edited-row': editElementIndex === index
        }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
                disabled
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.office }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <mdb-select [(ngModel)]="data.office" [disabled]="true">
                <mdb-option
                  *ngFor="let option of options"
                  [value]="option.value"
                  >{{ option.label }}</mdb-option
                >
              </mdb-select>
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.employees }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="number"
                class="form-control"
                [(ngModel)]="data.employees"
                disabled
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.international }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <div class="form-check ms-1 mt-1">
              <input
                mdbCheckbox
                class="form-check-input"
                type="checkbox"
                [(ngModel)]="data.international"
                disabled
              />
            </div>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="editElementIndex = index"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              (click)="onDeleteClick(data)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </td>
      </tr>
    </tbody>
  </table>
  <mdb-table-pagination
    #pagination
    [entries]="5"
    [disabled]="addRow || editElementIndex !== -1"
  ></mdb-table-pagination>
</div>
import { Component, ViewChild } from '@angular/core';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';

export interface Person {
  company: string;
  office: string;
  employees: number | null;
  international: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  editElementIndex = -1;
  addRow = false;

  newRow: Person = {
    company: '',
    office: 'Warsaw',
    employees: 1,
    international: false,
  };

  options = [
    { value: 'London', label: 'London' },
    { value: 'Warsaw', label: 'Warsaw' },
    { value: 'New York', label: 'New York' },
  ];

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Office', field: 'office', disableSort: true },
    { label: 'Employees', field: 'employees', disableSort: false },
    { label: 'International', field: 'international', disableSort: false },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      office: 'London',
      employees: 30,
      international: true,
    },
    {
      company: 'P.J. Company',
      office: 'London',
      employees: 80,
      international: false,
    },
    {
      company: 'Food & Wine',
      office: 'London',
      employees: 12,
      international: false,
    },
    {
      company: 'IT Service',
      office: 'London',
      employees: 17,
      international: false,
    },
    {
      company: 'A. Jonson Gallery',
      office: 'London',
      employees: 4,
      international: false,
    },
    {
      company: 'F.A. Architects',
      office: 'London',
      employees: 4,
      international: false,
    },
  ];

  constructor() {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow(): void {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }
}

Confirm delete

Note: This example use Popconfirm. Remember to import them.


Company Office Employees International Actions
Smith & JohnsonLondon30true
P.J. CompanyLondon80false
Food & WineLondon12false
IT ServiceLondon17false
A. Jonson GalleryLondon4false

Rows per page:

5
1 - 5 of 6
<div class="d-flex justify-content-end mb-4">
  <mdb-form-control>
    <input
      mdbInput
      type="text"
      class="form-control"
      id="search-input"
      [disabled]="addRow || editElementIndex !== -1"
      (keyup)="search($event)"
    />
    <label mdbLabel class="form-label" for="search-input">Search</label>
  </mdb-form-control>
  <button
    mdbRipple
    class="btn btn-primary btn-sm ms-3"
    [disabled]="addRow || editElementIndex !== -1"
    (click)="addRow = true"
  >
    <i class="fa fa-plus"></i>
  </button>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{
    'edited-table': addRow || editElementIndex !== -1
  }"
>
  <table
    class="table datatable-table"
    mdbTable
    mdbTableSort
    #table="mdbTable"
    #sort="mdbTableSort"
    [dataSource]="dataSource"
    [sort]="sort"
    [pagination]="pagination"
  >
    <thead class="datatable-header">
      <tr>
        <th
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr
        *ngIf="addRow"
        [ngClass]="{ 'edited-row': addRow }"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <mdb-select [(ngModel)]="newRow.office">
              <mdb-option
                *ngFor="let option of options"
                [value]="option.value"
                >{{ option.label }}</mdb-option
              >
            </mdb-select>
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="number"
              class="form-control"
              [(ngModel)]="newRow.employees"
            />
          </mdb-form-control>
        </td>
        <td>
          <div class="form-check ms-1 mt-1">
            <input
              mdbCheckbox
              class="form-check-input"
              type="checkbox"
              [(ngModel)]="newRow.international"
            />
          </div>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{ 'edited-row': editElementIndex === index }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.office }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <mdb-select [(ngModel)]="data.office">
                <mdb-option
                  *ngFor="let option of options"
                  [value]="option.value"
                  >{{ option.label }}</mdb-option
                >
              </mdb-select>
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.employees }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="number"
                class="form-control"
                [(ngModel)]="data.employees"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.international }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <div class="form-check ms-1 mt-1">
              <input
                mdbCheckbox
                class="form-check-input"
                type="checkbox"
                [(ngModel)]="data.international"
              />
            </div>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="onEditClick(index)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              #target
              (click)="openPopconfirm(target, data)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="onDiscardEdit(index)"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </td>
      </tr>
    </tbody>
  </table>
  <mdb-table-pagination
    #pagination
    [entries]="5"
    [disabled]="addRow || editElementIndex !== -1"
  ></mdb-table-pagination>
</div>
import { Component, ViewChild } from '@angular/core';
import {
  MdbPopconfirmRef,
  MdbPopconfirmService,
} from 'mdb-angular-ui-kit/popconfirm';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';
import { PopconfirmComponent } from './popconfirm.component';

export interface Person {
  company: string;
  office: string;
  employees: number | null;
  international: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  popconfirmRef: MdbPopconfirmRef<PopconfirmComponent> | null = null;
  editElementIndex = -1;
  addRow = false;

  newRow: Person = {
    company: '',
    office: 'Warsaw',
    employees: 1,
    international: false,
  };

  editRow: Person = {
    company: '',
    office: '',
    employees: null,
    international: false,
  };

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Office', field: 'office', disableSort: true },
    { label: 'Employees', field: 'employees', disableSort: false },
    { label: 'International', field: 'international', disableSort: false },
  ];

  options = [
    { value: 'London', label: 'London' },
    { value: 'Warsaw', label: 'Warsaw' },
    { value: 'New York', label: 'New York' },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      office: 'London',
      employees: 30,
      international: true,
    },
    {
      company: 'P.J. Company',
      office: 'London',
      employees: 80,
      international: false,
    },
    {
      company: 'Food & Wine',
      office: 'London',
      employees: 12,
      international: false,
    },
    {
      company: 'IT Service',
      office: 'London',
      employees: 17,
      international: false,
    },
    {
      company: 'A. Jonson Gallery',
      office: 'London',
      employees: 4,
      international: false,
    },
    {
      company: 'F.A. Architects',
      office: 'London',
      employees: 4,
      international: false,
    },
  ];

  constructor(private popconfirmService: MdbPopconfirmService) {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow() {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  onEditClick(index: number): void {
    this.editElementIndex = index;
    this.editRow = { ...this.table.data[index] };
  }

  onDiscardEdit(index: number): void {
    this.editElementIndex = -1;
    this.table.data[index] = { ...this.editRow };
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }

  openPopconfirm(target: HTMLElement, data: Person): void {
    this.popconfirmRef = this.popconfirmService.open(
      PopconfirmComponent,
      target,
      { data: { data: data } }
    );
    this.popconfirmRef.onClose.subscribe(() => {
      this.editElementIndex = -1;
    });
    this.popconfirmRef.onConfirm.subscribe((data) => {
      this.onDeleteClick(data);
    });
  }
}
<div class="popconfirm-popover shadow-4">
  <div class="popconfirm">
    <p class="popconfirm-message">
      <span class="popconfirm-message-text"
        >Are you sure you want to delete this entry?</span
      >
    </p>
    <div class="popconfirm-buttons-container">
      <button
        (click)="popconfirmRef.close()"
        type="button"
        aria-label="Cancel"
        class="btn btn-flat btn-sm"
      >
        Cancel
      </button>
      <button
        (click)="popconfirmRef.confirm(data)"
        type="button"
        aria-label="Confirm"
        class="btn btn-primary btn-sm"
      >
        Delete
      </button>
    </div>
  </div>
</div>
import { Component, OnInit } from '@angular/core';
import { MdbPopconfirmRef } from 'mdb-angular-ui-kit/popconfirm';

@Component({
  selector: 'app-popconfirm',
  templateUrl: './popconfirm.component.html',
})
export class PopconfirmComponent implements OnInit {
  data: any = null;

  constructor(public popconfirmRef: MdbPopconfirmRef<PopconfirmComponent>) {}

  ngOnInit(): void {}
}


Async data


Company Email Name Phone Actions

Loading results...

Rows per page:

10
1 - 0 of 0
<div class="d-flex justify-content-between mb-4">
  <button class="btn btn-primary btn-sm" (click)="loadData()">Load data</button>
  <div class="d-flex">
    <mdb-form-control>
      <input
        mdbInput
        type="text"
        class="form-control"
        id="search-input"
        [disabled]="addRow || editElementIndex !== -1 || loading"
        (keyup)="search($event)"
      />
      <label mdbLabel class="form-label" for="search-input">Search</label>
    </mdb-form-control>
    <button
      mdbRipple
      class="btn btn-primary btn-sm ms-3"
      [disabled]="addRow || editElementIndex !== -1 || loading"
      (click)="addRow = true"
    >
      <i class="fa fa-plus"></i>
    </button>
  </div>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{
    'edited-table': addRow || editElementIndex !== -1
  }"
>
  <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.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body" *ngIf="!loading">
      <tr
        *ngIf="addRow"
        [ngClass]="{ 'edited-row': addRow }"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.email"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.name"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.phone"
            />
          </mdb-form-control>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{ 'edited-row': editElementIndex === index }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.email }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.email"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.name }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.name"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.phone }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.phone"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="onEditClick(index)"
              [disabled]="editElementIndex !== -1 && editElementIndex !== index"
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              (click)="onDeleteClick(data)"
              [disabled]="editElementIndex !== -1 && editElementIndex !== index"
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="onDiscardEdit(index)"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </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>
  <mdb-table-pagination
    #pagination
    [entries]="10"
    [disabled]="addRow || editElementIndex !== -1 || loading"
  ></mdb-table-pagination>
</div>
import { HttpClient } from '@angular/common/http';
import { Component, ViewChild } from '@angular/core';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';
import { tap, take } from 'rxjs/operators';

interface Person {
  company: string;
  email: string;
  name: string;
  phone: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  dataUrl = 'https://jsonplaceholder.typicode.com/users';
  loading = true;
  editElementIndex = -1;
  addRow = false;

  newRow: Person = {
    company: '',
    email: '',
    name: '',
    phone: '',
  };

  editRow: Person = {
    company: '',
    email: '',
    name: '',
    phone: '',
  };

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Email', field: 'email', disableSort: false },
    { label: 'Name', field: 'name', disableSort: false },
    { label: 'Phone', field: 'phone', disableSort: false },
  ];

  dataSource: Person[] = [];

  constructor(private _http: HttpClient) {}

  loadData() {
    this.getData()
      .pipe(take(1))
      .subscribe((data: any[]) => {
        const mappedData = data.map((entry) => {
          return { ...entry, company: entry.company.name };
        });
        this.dataSource = mappedData;
      });
  }

  getData() {
    return this._http
      .get<any>(this.dataUrl)
      .pipe(tap(() => (this.loading = false)));
  }

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow(): void {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.newRow.company = '';
    this.newRow.email = '';
    this.newRow.name = '';
    this.newRow.phone = '';
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.email = '';
    this.newRow.name = '';
    this.newRow.phone = '';
    this.addRow = false;
  }

  onEditClick(index: number): void {
    this.editElementIndex = index;
    this.editRow.company = this.table.data[index].company;
    this.editRow.email = this.table.data[index].email;
    this.editRow.name = this.table.data[index].name;
    this.editRow.phone = this.table.data[index].phone;
  }

  onDiscardEdit(index: number): void {
    this.editElementIndex = -1;
    this.table.data[index].company = this.editRow.company;
    this.table.data[index].email = this.editRow.email;
    this.table.data[index].name = this.editRow.name;
    this.table.data[index].phone = this.editRow.phone;
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }
}

Custom rows

M.B.

(5 Avenue 26, New York)

Berkley & Clark

(43th Street 12, New York)

D&D Inc.

(14 Street 67, New York)

Thomas & Co.

(2 Avenue 54, New York)


Company Address City Actions
Smith & JohnsonPark Lane 2London
P.J. CompanyOak Street 7Aberdeen
Food & WineNetherhall Gardens 3Hampstead
IT ServiceWarwick Road 14London
A. Jonson GalleryOaklands Avenue 2London
F.A. ArchitectsFrognal Way 7Hampstead
<div class="row">
  <div class="col-md-3 col-sm-6 p-3">
    <h4>M.B.</h4>
    <p>(5 Avenue 26, New York)</p>
    <button
      class="btn btn-primary btn-sm"
      (click)="loadMB()"
      [disabled]="mBLoaded || addRow"
    >
      {{ mBLoaded ? "Loaded" : "Load into table" }}
    </button>
  </div>
  <div class="col-md-3 col-sm-6 p-3">
    <h4>Berkley & Clark</h4>
    <p>(43th Street 12, New York)</p>
    <button
      class="btn btn-primary btn-sm"
      (click)="loadBarkleyAndClark()"
      [disabled]="barkleyAndClarkLoaded || addRow"
    >
      {{ barkleyAndClarkLoaded ? "Loaded" : "Load into table" }}
    </button>
  </div>
  <div class="col-md-3 col-sm-6 p-3">
    <h4>D&D Inc.</h4>
    <p>(14 Street 67, New York)</p>
    <button
      class="btn btn-primary btn-sm"
      (click)="loadDAndDInc()"
      [disabled]="dAndDIncLoaded || addRow"
    >
      {{ dAndDIncLoaded ? "Loaded" : "Load into table" }}
    </button>
  </div>
  <div class="col-md-3 col-sm-6 p-3">
    <h4>Thomas & Co.</h4>
    <p>(2 Avenue 54, New York)</p>
    <button
      class="btn btn-primary btn-sm"
      (click)="loadThomasAndCo()"
      [disabled]="thomasAndCoLoaded || addRow"
    >
      {{ thomasAndCoLoaded ? "Loaded" : "Load into table" }}
    </button>
  </div>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{
    'edited-table': addRow || editElementIndex !== -1
  }"
>
  <table
    class="table datatable-table"
    mdbTable
    mdbTableSort
    #table="mdbTable"
    #sort="mdbTableSort"
    [dataSource]="dataSource"
    [sort]="sort"
  >
    <thead class="datatable-header">
      <tr>
        <th
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr
        *ngIf="addRow"
        [ngClass]="{ 'edited-row': addRow }"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.address"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.city"
            />
          </mdb-form-control>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{ 'edited-row': editElementIndex === index }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.address }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.address"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.city }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.city"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="onEditClick(index)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              (click)="onDeleteClick(data)"
              [disabled]="
                addRow ||
                (editElementIndex !== -1 && editElementIndex !== index)
              "
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="editElementIndex = -1"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="onDiscardEdit(index)"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </td>
      </tr>
    </tbody>
  </table>
</div>
import { Component, ViewChild } from '@angular/core';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';

export interface Person {
  company: string;
  address: string;
  city: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  editElementIndex = -1;
  addRow = false;
  mBLoaded = false;
  barkleyAndClarkLoaded = false;
  dAndDIncLoaded = false;
  thomasAndCoLoaded = false;

  newRow: Person = {
    company: '',
    address: '',
    city: '',
  };

  editRow: Person = {
    company: '',
    address: '',
    city: '',
  };

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Address', field: 'address', disableSort: false },
    { label: 'City', field: 'city', disableSort: false },
  ];

  dataSource: Person[] = [
    { company: 'Smith & Johnson', address: 'Park Lane 2', city: 'London' },
    { company: 'P.J. Company', address: 'Oak Street 7', city: 'Aberdeen' },
    {
      company: 'Food & Wine',
      address: 'Netherhall Gardens 3',
      city: 'Hampstead',
    },
    { company: 'IT Service', address: 'Warwick Road 14', city: 'London' },
    {
      company: 'A. Jonson Gallery',
      address: 'Oaklands Avenue 2',
      city: 'London',
    },
    { company: 'F.A. Architects', address: 'Frognal Way 7', city: 'Hampstead' },
  ];
  constructor() {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow(): void {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.newRow.company = '';
    this.newRow.address = '';
    this.newRow.city = 'null';
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.address = '';
    this.newRow.city = 'null';
    this.addRow = false;
  }

  onEditClick(index: number): void {
    this.editElementIndex = index;
    this.editRow = { ...this.table.data[index] };
  }

  onDiscardEdit(index: number): void {
    this.editElementIndex = -1;
    this.table.data[index] = { ...this.editRow };
  }

  onDeleteClick(data: Person) {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }

  loadMB(): void {
    const row = {
      company: 'M.B.',
      address: '5 Avenue 26',
      city: 'New York',
    };
    this.mBLoaded = true;
    this.addRow = true;
    this.newRow = row;
  }

  loadBarkleyAndClark(): void {
    const row = {
      company: 'Berkley & Clark',
      address: '43th Street 12',
      city: 'New York',
    };
    this.barkleyAndClarkLoaded = true;
    this.addRow = true;
    this.newRow = row;
  }

  loadDAndDInc(): void {
    const row = {
      company: 'D&D Inc.',
      address: '14 Street 67',
      city: 'New York',
    };
    this.dAndDIncLoaded = true;
    this.addRow = true;
    this.newRow = row;
  }

  loadThomasAndCo(): void {
    const row = {
      company: 'Thomas & Co.',
      address: '2 Avenue 54',
      city: 'New York',
    };
    this.thomasAndCoLoaded = true;
    this.addRow = true;
    this.newRow = row;
  }
}

Notifications

Note: This example use Alerts Remember to import them.


Company Office Employees International Actions
Smith & JohnsonLondon30true
P.J. CompanyLondon80false
Food & WineLondon12false
IT ServiceLondon17false
A. Jonson GalleryLondon4false
F.A. ArchitectsLondon4false

Rows per page:

10
1 - 6 of 6
<div class="d-flex justify-content-end mb-4">
  <mdb-form-control>
    <input
      mdbInput
      type="text"
      class="form-control"
      id="search-input"
      [disabled]="addRow || editElementIndex !== -1"
      (keyup)="search($event)"
    />
    <label mdbLabel class="form-label" for="search-input">Search</label>
  </mdb-form-control>
  <button
    mdbRipple
    class="btn btn-primary btn-sm ms-3"
    [disabled]="editElementIndex !== -1"
    (click)="addRow = true"
  >
    <i class="fa fa-plus"></i>
  </button>
</div>
<hr />
<div
  class="datatable table-editor mt-4"
  [ngClass]="{
    'edited-table': addRow || editElementIndex !== -1
  }"
>
  <table
    class="table datatable-table"
    mdbTable
    mdbTableSort
    #table="mdbTable"
    #sort="mdbTableSort"
    [dataSource]="dataSource"
    [sort]="sort"
    [pagination]="pagination"
  >
    <thead class="datatable-header">
      <tr>
        <th
          *ngFor="let header of headers"
          [mdbTableSortHeader]="header.field"
          [disableSort]="header.disableSort"
          scope="col"
        >
          {{ header.label | titlecase }}
        </th>
        <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody class="datatable-body">
      <tr
        *ngIf="addRow"
        [ngClass]="{ 'edited-row': addRow }"
        scope="row"
        cdkTrapFocus
        cdkTrapFocusAutoCapture="true"
      >
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="text"
              class="form-control"
              [(ngModel)]="newRow.company"
            />
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <mdb-select [(ngModel)]="newRow.office">
              <mdb-option
                *ngFor="let option of options"
                [value]="option.value"
                >{{ option.label }}</mdb-option
              >
            </mdb-select>
          </mdb-form-control>
        </td>
        <td>
          <mdb-form-control>
            <input
              mdbInput
              type="number"
              class="form-control"
              [(ngModel)]="newRow.employees"
            />
          </mdb-form-control>
        </td>
        <td>
          <div class="form-check ms-1 mt-1">
            <input
              mdbCheckbox
              class="form-check-input"
              type="checkbox"
              [(ngModel)]="newRow.international"
            />
          </div>
        </td>
        <td>
          <button
            class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
            (click)="addNewRow()"
          >
            <i class="fa fa-check"></i>
          </button>
          <button
            class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
            (click)="discardNewRow()"
          >
            <i class="fa fa-ban"></i>
          </button>
        </td>
      </tr>
      <tr
        *ngFor="let data of table.data; let index = index"
        scope="row"
        [cdkTrapFocus]="editElementIndex === index"
        [cdkTrapFocusAutoCapture]="editElementIndex === index"
        [ngClass]="{ 'edited-row': editElementIndex === index }"
      >
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.company }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="text"
                class="form-control"
                [(ngModel)]="data.company"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.office }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <mdb-select [(ngModel)]="data.office">
                <mdb-option
                  *ngFor="let option of options"
                  [value]="option.value"
                  >{{ option.label }}</mdb-option
                >
              </mdb-select>
            </mdb-form-control>
          </ng-container>
        </td>
        <td style="min-width: 250px; max-width: 250px">
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.employees }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <mdb-form-control>
              <input
                mdbInput
                type="number"
                class="form-control"
                [(ngModel)]="data.employees"
              />
            </mdb-form-control>
          </ng-container>
        </td>
        <td>
          <ng-container *ngIf="editElementIndex !== index">
            {{ data.international }}
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <div class="form-check ms-1 mt-1">
              <input
                mdbCheckbox
                class="form-check-input"
                type="checkbox"
                [(ngModel)]="data.international"
              />
            </div>
          </ng-container>
        </td>
        <td>
          <ng-container
            *ngIf="editElementIndex === -1 || editElementIndex !== index"
          >
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark edit-button"
              (click)="onEditClick(index)"
              [disabled]="editElementIndex !== -1 && editElementIndex !== index"
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark delete-button"
              (click)="onDeleteClick(data)"
              [disabled]="editElementIndex !== -1 && editElementIndex !== index"
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </ng-container>
          <ng-container *ngIf="editElementIndex === index">
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-dark save-button"
              (click)="onSaveClick(data)"
            >
              <i class="fa fa-check"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-dark discard-button"
              (click)="onDiscardEdit(index)"
            >
              <i class="fa fa-ban"></i>
            </button>
          </ng-container>
        </td>
      </tr>
    </tbody>
  </table>
  <mdb-table-pagination
    #pagination
    [entries]="5"
    [disabled]="addRow || editElementIndex !== -1"
  ></mdb-table-pagination>
</div>
import { Component, ViewChild } from '@angular/core';
import {
  MdbNotificationService,
  MdbNotificationRef,
} from 'mdb-angular-ui-kit/notification';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';
import { NotificationComponent } from './notification.component';

export interface Person {
  company: string;
  office: string;
  employees: number | null;
  international: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  notificationRef: MdbNotificationRef<NotificationComponent> | null = null;
  editElementIndex = -1;
  addRow = false;

  newRow: Person = {
    company: '',
    office: 'Warsaw',
    employees: 1,
    international: false,
  };

  editRow: Person = {
    company: '',
    office: '',
    employees: null,
    international: false,
  };

  options = [
    { value: 'London', label: 'London' },
    { value: 'Warsaw', label: 'Warsaw' },
    { value: 'New York', label: 'New York' },
  ];

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Office', field: 'office', disableSort: true },
    { label: 'Employees', field: 'employees', disableSort: false },
    { label: 'International', field: 'international', disableSort: false },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      office: 'London',
      employees: 30,
      international: true,
    },
    {
      company: 'P.J. Company',
      office: 'London',
      employees: 80,
      international: false,
    },
    {
      company: 'Food & Wine',
      office: 'London',
      employees: 12,
      international: false,
    },
    {
      company: 'IT Service',
      office: 'London',
      employees: 17,
      international: false,
    },
    {
      company: 'A. Jonson Gallery',
      office: 'London',
      employees: 4,
      international: false,
    },
    {
      company: 'F.A. Architects',
      office: 'London',
      employees: 4,
      international: false,
    },
  ];

  constructor(private notificationService: MdbNotificationService) {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  addNewRow(): void {
    this.dataSource = [...this.dataSource, { ...this.newRow }];
    this.openAlert(this.newRow, 'add');
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.newRow.international = false;
    this.addRow = false;
  }

  discardNewRow(): void {
    this.newRow.company = '';
    this.newRow.office = 'Warsaw';
    this.newRow.employees = 1;
    this.addRow = false;
  }

  onEditClick(index: number): void {
    this.editElementIndex = index;
    this.editRow = { ...this.table.data[index] };
  }

  onDiscardEdit(index: number): void {
    this.editElementIndex = -1;
    this.table.data[index] = { ...this.editRow };
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
    this.openAlert(data, 'delete');
  }

  onSaveClick(data: Person): void {
    this.editElementIndex = -1;
    this.openAlert(data, 'edit');
  }

  openAlert(data: Person, action: 'add' | 'delete' | 'edit'): void {
    const options = {
      action: action,
      rowData: `${data.company} (${data.office})`,
    };
    this.notificationRef = this.notificationService.open(
      NotificationComponent,
      { data: options, autohide: true, delay: 1000 }
    );
  }
}
<div class="alert alert-{{ color }}" role="alert">
  <strong>{{ actionText }}</strong> {{ rowData }}
</div>
import { Component, OnInit } from '@angular/core';
import { MdbNotificationRef } from 'mdb-angular-ui-kit/notification';

@Component({
  selector: 'app-notification',
  templateUrl: './notification.component.html',
})
export class NotificationComponent implements OnInit {
  action: 'add' | 'delete' | 'edit' | null = null;
  rowData: string | null = null;
  color: string | null = null;
  actionText: string | null = null;

  constructor(
    public notificationRef: MdbNotificationRef<NotificationComponent>
  ) {}

  ngOnInit(): void {
    switch (this.action) {
      case 'add':
        this.color = 'success';
        this.actionText = 'New entry:';
        break;
      case 'delete':
        this.color = 'danger';
        this.actionText = 'Deleted entry:';
        break;
      case 'edit':
        this.color = 'primary';
        this.actionText = 'Updated entry:';
        break;
      default:
        break;
    }
  }
}

Dark

Note: This example use Modal. Remember to import them.


Company Address Employees Actions
Smith & JohnsonPark Lane 2, London30
P.J. CompanyOak Street 7, Aberdeen80
Food & WineNetherhall Gardens 3, Hampstead12
IT ServiceWarwick Road 14, London17
A. Jonson GalleryOaklands Avenue 2, London4

Rows per page:

5
1 - 5 of 6
<section class="border p-4 mb-4 bg-dark">
  <div class="d-flex justify-content-end mb-4">
    <mdb-form-control class="form-white">
      <input
        mdbInput
        type="text"
        class="form-control"
        id="search-input"
        (keyup)="search($event)"
      />
      <label mdbLabel class="form-label" for="search-input">Search</label>
    </mdb-form-control>
    <button
      mdbRipple
      class="btn btn-outline-light btn-sm ms-3"
      (click)="openModal('add')"
    >
      <i class="fa fa-plus"></i>
    </button>
  </div>
  <hr />
  <div
    class="datatable table-editor bg-dark datatable-dark text-white border-white mt-4"
  >
    <table
      class="table datatable-table"
      mdbTable
      mdbTableSort
      #table="mdbTable"
      #sort="mdbTableSort"
      [dataSource]="dataSource"
      [sort]="sort"
      [pagination]="pagination"
    >
      <thead class="datatable-header text-white">
        <tr>
          <th
            *ngFor="let header of headers"
            [mdbTableSortHeader]="header.field"
            [disableSort]="header.disableSort"
            scope="col"
          >
            {{ header.label | titlecase }}
          </th>
          <th scope="col">Actions</th>
        </tr>
      </thead>
      <tbody class="datatable-body text-white">
        <tr *ngFor="let data of table.data; let index = index" scope="row">
          <td style="min-width: 250px; max-width: 250px">
            {{ data.company }}
          </td>
          <td style="min-width: 250px; max-width: 250px">
            {{ data.address }}
          </td>
          <td style="min-width: 250px; max-width: 250px">
            {{ data.employees }}
          </td>

          <td>
            <button
              class="me-2 m-0 p-0 shadow-0 btn btn-lg text-light edit-button"
              (click)="openModal('edit', data)"
            >
              <i class="far fa-edit"></i>
            </button>
            <button
              class="m-0 p-0 shadow-0 btn btn-lg text-light delete-button"
              (click)="onDeleteClick(data)"
            >
              <i class="far fa-trash-alt"></i>
            </button>
          </td>
        </tr>
      </tbody>
    </table>
    <mdb-table-pagination #pagination [entries]="5"></mdb-table-pagination>
  </div>
</section>
import { Component, ViewChild } from '@angular/core';
import { MdbModalRef, MdbModalService } from 'mdb-angular-ui-kit/modal';
import { MdbTableDirective } from 'mdb-angular-ui-kit/table';
import { ModalComponent } from './modal.component';

export interface Person {
  company: string;
  address: string;
  employees: number | null;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  @ViewChild('table') table!: MdbTableDirective<Person>;

  modalRef: MdbModalRef<ModalComponent> | null = null;

  headers = [
    { label: 'Company', field: 'company', disableSort: false },
    { label: 'Address', field: 'address', disableSort: false },
    { label: 'Employees', field: 'employees', disableSort: false },
  ];

  dataSource: Person[] = [
    {
      company: 'Smith & Johnson',
      address: 'Park Lane 2, London',
      employees: 30,
    },
    {
      company: 'P.J. Company',
      address: 'Oak Street 7, Aberdeen',
      employees: 80,
    },
    {
      company: 'Food & Wine',
      address: 'Netherhall Gardens 3, Hampstead',
      employees: 12,
    },
    {
      company: 'IT Service',
      address: 'Warwick Road 14, London	',
      employees: 17,
    },
    {
      company: 'A. Jonson Gallery',
      address: 'Oaklands Avenue 2, London	',
      employees: 4,
    },
    {
      company: 'F.A. Architects',
      address: 'Frognal Way 7, Hampstead	',
      employees: 4,
    },
  ];
  constructor(private modalService: MdbModalService) {}

  search(event: Event): void {
    const searchTerm = (event.target as HTMLInputElement).value;
    this.table.search(searchTerm);
  }

  openModal(mode: 'add' | 'edit', data?: Person): void {
    this.modalRef = this.modalService.open(ModalComponent, {
      data: {
        modalTitle: mode === 'edit' ? 'Edit item' : 'New item',
        company: data ? data.company : '',
        address: data ? data.address : '',
        employees: data ? data.employees : null,
      },
    });
    this.modalRef.onClose.subscribe((modalData: Person) => {
      if (!modalData) {
        return;
      }
      if (mode === 'add') {
        this.dataSource = [...this.dataSource, { ...modalData }];
      } else if (mode === 'edit' && data) {
        const index = this.dataSource.indexOf(data);
        this.dataSource[index] = modalData;
        this.dataSource = [...this.dataSource];
      }
    });
  }

  onDeleteClick(data: Person): void {
    const index = this.dataSource.indexOf(data);
    this.dataSource.splice(index, 1);
    this.dataSource = [...this.dataSource];
  }
}
<div class="modal-header bg-dark text-white">
  <h5 class="modal-title" id="exampleModalLabel">{{ modalTitle }}</h5>
</div>
<div class="modal-body bg-dark text-white">
  <div class="my-4 table-editor_input-wrapper">
    <mdb-form-control class="form-white">
      <input
        mdbInput
        type="text"
        id="company-input"
        class="form-control"
        [(ngModel)]="company"
      />
      <label mdbLabel class="form-label" for="company-input">Company</label>
    </mdb-form-control>
  </div>
  <div class="my-4 table-editor_input-wrapper">
    <mdb-form-control class="form-white">
      <input
        mdbInput
        type="text"
        id="address-input"
        class="form-control"
        [(ngModel)]="address"
      />
      <label mdbLabel class="form-label" for="address-input">Address</label>
    </mdb-form-control>
  </div>
  <div class="my-4 table-editor_input-wrapper">
    <mdb-form-control class="form-white">
      <input
        mdbInput
        type="number"
        id="employees-input"
        class="form-control"
        [(ngModel)]="employees"
      />
      <label mdbLabel class="form-label" for="employees-input">Employees</label>
    </mdb-form-control>
  </div>
</div>
<div class="modal-footer bg-dark text-white">
  <button
    type="button"
    class="shadow-0 btn btn-md btn-outline-light"
    (click)="modalRef.close()"
  >
    Cancel
  </button>
  <button
    type="button"
    class="shadow-0 btn btn-md btn-light"
    (click)="saveData()"
  >
    Save
  </button>
</div>
import { Component, OnInit } from '@angular/core';
import { MdbModalRef } from 'mdb-angular-ui-kit/modal';

@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html',
})
export class ModalComponent implements OnInit {
  modalTitle: string | null = null;
  company: string | null = null;
  address: string | null = null;
  employees: string | null = null;

  options = [
    { value: 'London', label: 'London' },
    { value: 'Warsaw', label: 'Warsaw' },
    { value: 'New York', label: 'New York' },
  ];

  constructor(public modalRef: MdbModalRef<ModalComponent>) {}

  ngOnInit(): void {}

  saveData(): void {
    const closeMessage = {
      company: this.company,
      employees: this.employees,
      address: this.address,
    };

    this.modalRef.close(closeMessage);
  }
}

Table editor - API


Import

import { MdbTableModule } from 'mdb-angular-ui-kit/table';
import { MdbFormsModule } from 'mdb-angular-ui-kit/forms';
import { FormsModule } from '@angular/forms';
import { A11yModule } from '@angular/cdk/a11y';
import { MdbSelectModule } from 'mdb-angular-ui-kit/select';              // For examples with Select
import { MdbModalModule } from 'mdb-angular-ui-kit/modal';                // For examples with Modal
import { MdbNotificationModule } from 'mdb-angular-ui-kit/notification';  // For examples with Notification
import { MdbPopconfirmModule } from 'mdb-angular-ui-kit/popconfirm';      // For examples with Popconfirm

...
@NgModule({
  ...
  imports: [
    MdbTableModule,
    MdbFormsModule,
    FormsModule,
    A11yModule,
    MdbSelectModule,        // For examples with Select
    MdbModalModule,         // For examples with Modal
    MdbNotificationModule,  // For examples with Notification
    MdbPopconfirmModule     // For examples with Popconfirm
  ],
  ...
})