Reusable Mat Table

Yamuna
4 min readFeb 22, 2023

--

Introduction:

A reusable mat-table is a powerful and flexible component in Angular Material that allows you to display and manipulate data in a table format. This article might be helpful to you, if you are using more data table in your angular project.

By using a reusable mat-table, you can create a consistent user experience across your application, reduce code duplication, and improve maintainablity. It provides a range of features such as sorting, filtering , pagination and row selection, which can be easily configured and adapted to meet your specific requirements.

Let’s Start here

  1. Create a new Angular Project by using the command
ng new reusable-mat-table

2. Install angular material by using the command

ng add @angular/material

And add the MatTableModule and other required material modules in your app.module.ts file.

3. Create a new component by using the command

ng generate component mat-table

Now your app.module.ts will look like this

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MatTableModule } from '@angular/material/table';
import { MatIconModule } from '@angular/material/icon';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

import { ReusableMatTableComponent } from './reusable-mat-table/reusable-mat-table.component';

@NgModule({
declarations: [AppComponent, ReusableMatTableComponent],
imports: [BrowserModule,HttpClientModule, MatTableModule, MatIconModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}

4. In the mat-table component, we can define two variables with @Input() decorator and one event emitter with @Ouput() decorator

i. Data Source

The Data Source provides the data array to the table. We may create our own data or may receive through API calls as an array of objects

Example for data source

[
{"position": 1, "name": "Hydrogen", "weight": 1.0079, "symbol":"H"},
{"position": 2, "name": "Helium", "weight": 4.0026, "symbol": "He"},
{"position": 3, "name": "Lithium", "weight": 6.941, "symbol": "Li"},
{"position": 4, "name": "Beryllium", "weight": 9.0122, "symbol": "Be"}
]

ii. Displayed Columns

Displayed Columns will define the row and column templates for our data table. Here I have defined a interface with configurable rows and columns

export interface TableColumn {
caption: string;
field: string;
config?: Config;
}
export interface Config{
isAction?:boolean;
isDate?:boolean;
actions:string[]
}

Here the caption is the header cell and each row cell will render by the field. I have used the config property to customize our table columns

Caption => HeaderCell

field => RowCell

Config

For example, I have used this config property with two options isAction and isDate

isAction => if isAction set as true, then we can give some actions to the datatable like view, edit, delete etc..,

isDate => if isDate set as true, then we can give dateformat to the table data.

 info_table_column: TableColumn[] = [
{ caption: 'SNO', field: 'sno' },
{ caption: 'Name', field: 'name' },
{
caption: 'Date of Birth',
field: 'dob',
config: { isDate: true},
},
{ caption: 'Gender', field: 'gender' },
{
caption: 'Action',
field: 'action',
config: { isAction: true, actions: ['visibility', 'delete', 'edit'] },
},
];

THE EVENT EMITTER…..

The event emitter might helpful to do some task based on the actions of table. So, we can declare a event emitter in mat-table component and this can emit the values to parent component whenever an action (view, edit, delete) is clicked.

  @Output() OnAction: EventEmitter<any> = new EventEmitter<any>();

Here, I have emitted the action and the row data element to the parent component on the click event of action button

    this.OnAction.emit({ action, element });

THE MAT-TABLE COMPONENT……..

Now we have the data source, displayed columns and a event emitter, let bind it to our mat-table component

<table mat-table class="mat-elevation-z4" [dataSource]="dataSource">
<ng-container *ngFor="let c of columnName; let i=index" [matColumnDef]="c.caption">
<ng-container>
<th mat-header-cell *matHeaderCellDef>
{{c.caption}}
</th>
</ng-container>

<td mat-cell *matCellDef="let element">
<ng-container *ngIf="!c.config else hasConfig">{{element[c.field]}}</ng-container>
<ng-template #hasConfig>
<ng-container *ngIf="c.config.isAction">
<mat-icon *ngFor="let action of c.config.actions" (click)="emitAction(action,element)" mat-button>{{ action
}}</mat-icon>
</ng-container>
<ng-container *ngIf="c.config.isDate">
{{element[c.field]|date:'dd/MM/YYYY'}}
</ng-container>
</ng-template>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

and the mat-table.component.ts will have the variables, function and the event emitters

import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { TableColumn } from '../app.component';

@Component({
selector: 'app-reusable-mat-table',
templateUrl: './reusable-mat-table.component.html',
styleUrls: ['./reusable-mat-table.component.css'],
})
export class ReusableMatTableComponent implements OnInit {
@Input() columnName: TableColumn[] =[];
@Input() dataSource: any;
@Output() OnAction: EventEmitter<any> = new EventEmitter<any>();
public displayedColumns: string[] | undefined;
constructor() {}

ngOnInit(): void {
this.displayedColumns = this.columnName.map(
(tableColumn: TableColumn) => tableColumn.caption
);
console.log(this.displayedColumns);
}
setDataSource(data: any) {
this.dataSource = new MatTableDataSource(data);
}
emitAction(action: string, element: any) {
this.OnAction.emit({ action, element });
console.log(action);
}
}

So the component is ready to use with another components

<app-reusable-mat-table 
[dataSource]="getTableData_periodicInfo$"
[columnName]="periodic_table_columns"
(onAction)="onActionMatTable($event)">

</app-reusable-mat-table>

Similarly we can add pagination filtering etc.., to the mat-table component as per our convenience.

And you can find this example in my github repo

https://stackblitz.com/edit/angular-ivy-mhkghg?file=README.md

Thanks for reading !! and this is my first blog, please give me your feedbacks, that may help me a lot to improve

--

--