Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@e-is/ngx-material-table

e-is543MIT18.0.3TypeScript support: included

Angular 17 table based on @angular/cdk table structure, to allow row insertion, edition, validation and deletion.

angular, angular 17, table, inline validation, material design, angular material table, ngx material table, ngx table

readme

Angular material table (Angular 10+)

Forked from angular4-material-table

This project extends @angular/cdk data-table, also used in @angular/material table.

It extends @angular/cdk/collections DataSource in order to include a row structure, allowing row creation, inline row edition, deletion and validation.

Supported angular versions:

  • Angular 17 (v17.x)
    • 17.3 (v17.3.x)
    • 17.2 (v17.2.x)
  • Angular 16 (v0.16.0)
  • Angular 15 (v0.15.0)
  • Angular 14 (v0.14.0)
  • Angular 11 (v0.11.0 and v0.12.0)
  • Angular 10 (v0.10.0)
  • Angular <= 9: Please use angular4-material-table

@e-is/ngx-material-table

Installation

To install the package run:

npm install @e-is/ngx-material-table

Example

Example of using @e-is/ngx-material-table:

@e-is/ngx-material-table

Other example

Use

Initial steps

To use this table, first of all you must check how use angular @angular/cdk data-table.

Useful data and methods

Using this extension, you can set CDK data-table datasource with an instance of TableDataSource.

Using TableDataSource allows you to have some row related methods and data to implement add/edit/remove elements:

class TableElement<T> {
  id: number;
  editing: boolean;
  currentData?: T;
  originalData?: T;
  source: TableDataSource<T>;
  validator: FormGroup; // Used only in reactive forms.

  delete(): void;
  confirmEditCreate(): boolean;
  startEdit(): void;
  cancelOrDelete(): void;
  isValid(): boolean; // Used only in reactive forms.
}
class TableDataSource<T> {

  constructor(
    data: T[],
    dataType?: new () => T,
    validatorService?: ValidatorService,
    config = { prependNewElements: false, suppressErrors: false });

  datasourceSubject: Subject<T[]>;

  updateDatasource(data: T[], options = { emitEvent: true }): void;

  createNew(): void;

  getRow(id: number): AsyncTableElement<T>;
}

Angular4 material table example

Angular material table use example: Example of @e-is/ngx-material-table use

See this package in action

Optional libraries

Optional libraries used in the example:

"@angular/material": "16.2.11",
"@angular/forms": 16.2.12", // <- For inline validation
"material-design-icons": "^3.0.1"

person-list-reactive-forms.component.html

<mat-table [dataSource]="dataSource">
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let row">
      <mat-form-field [floatLabel]="row.editing ? 'auto' : 'never'">
        <input matInput [formControl]="row.validator.controls['name']" placeholder="Name">
      </mat-form-field>
    </mat-cell>
  </ng-container>
  <ng-container matColumnDef="age">
    <mat-header-cell *matHeaderCellDef> Age </mat-header-cell>
    <mat-cell *matCellDef="let row">
      <mat-form-field [floatLabel]="row.editing ? 'auto' : 'never'">
        <input matInput [formControl]="row.validator.controls['age']" type="number" placeholder="Age">
      </mat-form-field>
    </mat-cell>
  </ng-container>
  <ng-container matColumnDef="actionsColumn">
    <mat-header-cell *matHeaderCellDef>
      <button mat-icon-button color="accent" (click)="dataSource.createNew()"><i class="fa fa-plus mat-icon"></i></button>
    </mat-header-cell>
    <mat-cell *matCellDef="let row">
      <button *ngIf="!row.editing" mat-icon-button color="primary" (click)="row.startEdit()">
        <mat-icon>edit</mat-icon>
      </button>
      <button *ngIf="row.editing" mat-icon-button color="primary" (click)="row.confirmEditCreate()">
        <mat-icon>done</mat-icon>
      </button>
      <button mat-icon-button color="primary" (click)="row.cancelOrDelete()">
        <mat-icon *ngIf="row.editing">undo</mat-icon>
        <mat-icon *ngIf="!row.editing">delete</mat-icon>
      </button>
    </mat-cell>
  </ng-container>

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

person-list-template-driven.component.html

<mat-table [dataSource]="dataSource">
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let row">
      <mat-form-field [floatLabel]="row.editing ? 'float' : 'never'">
        <input [(ngModel)]="row.currentData.name" placeholder="Name" [disabled]="!row.editing" matInput>
      </mat-form-field>
    </mat-cell>
  </ng-container>
  <ng-container matColumnDef="age">
    <mat-header-cell *matHeaderCellDef> Age </mat-header-cell>
    <mat-cell *matCellDef="let row">
      <mat-form-field [floatLabel]="row.editing ? 'float' : 'never'">
        <input type="number" [(ngModel)]="row.currentData.age" placeholder="Age"  [disabled]="!row.editing" matInput>
      </mat-form-field>
    </mat-cell>
  </ng-container>
  <ng-container matColumnDef="actionsColumn">
    <mat-header-cell *matHeaderCellDef>
      <button mat-icon-button color="accent" (click)="dataSource.createNew()"><i class="fa fa-plus mat-icon"></i></button>
    </mat-header-cell>
    <mat-cell *matCellDef="let row">
      <button *ngIf="!row.editing" mat-icon-button color="primary" (click)="row.startEdit()">
        <mat-icon>edit</mat-icon>
      </button>
      <button *ngIf="row.editing" mat-icon-button color="primary" (click)="row.confirmEditCreate()">
        <mat-icon>done</mat-icon>
      </button>
      <button mat-icon-button color="primary" (click)="row.cancelOrDelete()">
        <mat-icon *ngIf="row.editing">undo</mat-icon>
        <mat-icon *ngIf="!row.editing">delete</mat-icon>
      </button>
    </mat-cell>
  </ng-container>

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

person-list.component.ts

@Component({
  selector: 'app-person-list',
  providers: [
    {provide: ValidatorService, useClass: PersonValidatorService }
  ],
  templateUrl: './person-list.component.html',
})
export class PersonListComponent implements OnInit {

  constructor(private personValidator: ValidatorService) { }

  displayedColumns = ['name', 'age', 'actionsColumn'];

  @Input() personList;
  @Output() personListChange = new EventEmitter<Person[]>();

  dataSource: TableDataSource<Person>;


  ngOnInit() {
    this.dataSource = new TableDataSource<any>(this.personList, Person, this.personValidator);

    this.dataSource.datasourceSubject.subscribe(personList => this.personListChange.emit(personList));
  }
}

class Person {
  name: string;
  age: number;
}

@Injectable()
class PersonValidatorService implements ValidatorService {
  getRowValidator(): FormGroup {
    return new FormGroup({
      'name': new FormControl(null, Validators.required),
      'age': new FormControl(),
      });
  }
}

Contributions

Any suggestion or contribution will be appreciated.

Change log

See Change log