Skip to content

Material Table

sefirus edited this page Jun 9, 2022 · 12 revisions

Owerview

So, here you can see a tutorial for the angular material prebuild table, including button columns, rows sorting and filtering: image

Sourse code: https://github.com/sefirus/material-table-example

  • For the record, table is made to represent the folloving class:
export interface Procedure {
    id: number;
    name: string;
    description: string;
    duration: number;
    cost: number;
}

Getting started

Installing Angular Material

At first, you need to install and add amgular material to your project using these commands:

npm i -g @angular/material ng add @angular/material

Creating component and importing libraries

At first, go to app.module.ts and import the following modules:

import { MatFormFieldModule } from '@angular/material/form-field';   //Specially for filtering
import { MatInputModule } from '@angular/material/input'             //Specially for filtering
import { MatSortModule } from '@angular/material/sort';              //Specially for sorting
import { MatButtonModule } from '@angular/material/button';          //Specially for buttons
import { MatTableModule } from '@angular/material/table';

*Dont forget to write all of them inside imports

Than, create new component and go to the component`s typescript file, and import the following items:

import { MatSort } from '@angular/material/sort';                    //Specially for sorting
import { ViewChild } from '@angular/core';                           //Specially for sorting
import { MatTableDataSource } from '@angular/material/table';

Defining basic structure

After importing all libraries, go to the component`s typescript file, and under the imports section create a new array with the sample data for the table:

const DATA_SOURCE: Procedure[] = [
  {
    "id": 1,
    "name": "first procedure",
    "cost": 10,
    "description": "first procedure desription",
    "duration": 30
  },
  {
    "id": 2,
    "name": "second procedure",
    "cost": 25,
    "description": "sknd procedure desription",
    "duration": 25
  },
  {
    "id": 3,
    "name": "third procedure",
    "cost": 30,
    "description": "thrd procedure desription",
    "duration": 10
  },
  {
    "id": 4,
    "name": "fourth procedure",
    "cost": 45,
    "description": "frth procedure desription",
    "duration": 40
  },
  {
    "id": 5,
    "name": "fifth procedure",
    "cost": 50,
    "description": "fifth procedure desription",
    "duration": 35
  },
  {
    "id": 6,
    "name": "six procedure",
    "cost": 65,
    "description": "six procedure desription",
    "duration": 15
  },
  {
    "id": 7,
    "name": "sevens procedure",
    "cost": 70,
    "description": "sevens procedure desription",
    "duration": 10
  }
]

Next, go to the component`s class, and create two following wariables inside it:

 dataSource: MatTableDataSource<Procedure> = new MatTableDataSource(DATA_SOURCE);               //Special data class to handle a table
 displayedColumns: string[] = ['name', 'cost', 'description', 'duration', 'button'];    //List of column names to be displayed

Than, go to the component`s html file and paste the following code:

  • mat-mable inditates that table is a part of @angular/material so it can use all the features
  • [dataSource] stands for data sourse of the table. In fact, you can pass here any array with corresponding set of properties
<table 
    mat-table 
    [width]="700" 
    [dataSource]="dataSource">
  
</table>  

So, we created a basic structureof the component. Now you can`t see any table elements or colums, but a blank page, because they are not defined in html (in fact, you need to define all the columns from the displayedColumns list)

Creating a table

So, lets paste html code for the columns to the table:

  • ng-container stands for the definition of column`s container
  • matColumnDef="" stands for the element of the displayedColumns list whitc column will represent
  • mat-header-cell with *matHeaderCellDef stand for definition of column`s header
  • mat-cell stands for the definition of table cell
  • *matCellDef="let element" stands for the declaration of row`s wariable
  • mat-header-row and mat-row stand for definition of the row
  • *matHeaderRowDef="displayedColumns" stands for the declaration of header row columns
  • *matRowDef="let row; columns: displayedColumns;" stands for the declaration of regular row, with displayedColumns for columns of the row
    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let element"> {{element.name}} </td>
    </ng-container>

    <ng-container matColumnDef="cost">
        <th mat-header-cell *matHeaderCellDef> Cost(T) </th>
        <td mat-cell *matCellDef="let element"> {{element.cost}} </td>
    </ng-container>

    <ng-container matColumnDef="description">
        <th mat-header-cell *matHeaderCellDef> Description </th>
        <td mat-cell *matCellDef="let element"> {{element.description}} </td>
    </ng-container>

    <ng-container matColumnDef="duration">
        <th mat-header-cell *matHeaderCellDef> Duration </th>
        <td mat-cell *matCellDef="let element"> {{element.duration}} </td>
    </ng-container>

    <ng-container matColumnDef="button">
        <th mat-header-cell *matHeaderCellDef> Delete </th>
        <td mat-cell *matCellDef="let element"> 
            <button mat-raised-button (click)="onButtonclick(element)">B</button>
        </td>
    </ng-container>

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

Now, lets declare a method inside component`s class, that button will fire on click:

  onButtonclick(element : Procedure){
    console.log(element);
  }

*Note thaе i can pass an object of cells type to the method, called from cell (click on the first rows button):

image

Here we are! Now we have a basic angular material table: image

Sort

Now, lets add sort to the table. At first, declare a new MatSort object with decorator inside of the component's class, right under the displayedColumns:

  @ViewChild(MatSort) sort?: MatSort;

Than, we need to assign recently created sort to the dataSources sort property, but only anfter the view is initialized. Lets create a standart method ngAfterViewInit()` to do it:

  ngAfterViewInit(): void{
    this.dataSource.sort = this.sort!;
  }

Than, we need to add matSort directive to the table definition and mat-sort-header attribute to every column header of table. So, everything must look like this:

image

Here we are! We added sort to tables rows:

image

NOTE: You can play with different styles of sort direction arrow by using matSortXXX directives on the table definition

Filter

Now, lets add filtering to the table. At first, we need to create an input field, to retrieve a pattern to filter. Lets do in using angular material predifined mat-form-field input^:

  <mat-form-field style="width: 700px;" appearance="outline">
    <mat-label>Filter</mat-label>
    <input matInput placeholder="Placeholder" #input>
  </mat-form-field>

So, here we created such an inpur field:

image NOTE: You can choose any different input field

Now, lets inplement a method that will get failter pattern from passed event and perform angular built-in filtering:

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
  }

NOTE: this method searches every column of the table

And, last but not least, we need to call the method from the html input when te key is pressed. So, lets add direcrive (keyup)="applyFilter($event)" to the input tag like that: image

Here we are! Now we have fully implemented table with sorting and fitering! image