Filtering Column Definitions on Angular Material Tables

Reusable Design

IamGroot
3 min readMay 11, 2023

This tutorial is specifically for defining a reusable component that allows to display only certain columns of the data on Angular Material. This tutorial requires that you have a primary understanding of the Angular and Javascript basics.

The expected outcome of the tutorial would look like the below screenshot, in which the checkbox would have a functionality to hide columns that are not required for the user.

The UI for this project uses the mat-checkbox and mat-table .

For this tutorial we have used a dummy data given below to be shown in the table:

const ELEMENT_DATA: PeriodicElement[] = [
{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'},
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
  1. First step is to define a column definition interface and its for this object type which would be as individual property of the PeriodicElement object prototype as given below
export interface ColumnLabelDef{
// this property is the column name
label:string,
// this propety is used to check which columns are to be displayed on UI
valid:boolean
}

var COLUMN_DEF_DATA:ColumnLabelDef[] = [
{
label:"position",
valid:true
},
{
label:"name",
valid:true
},
{
label:"weight",
valid:true
},
{
label:"symbol",
valid:true
}
]

2. Define a data source as given below

newDataSource = new MatTableDataSource(ELEMENT_DATA as object[]);

The casting to object[] is important as updated data source would have a different type which would give a type casting exception later on

3. Define functions for getting the column names, getting the columns that are enabled, getting the status of all columns, toggling the column validity and processing the current data to filter out enabled columns only

  //getting the column names 
getColumnNames():string[]{
return COLUMN_DEF_DATA.map(col => col.label)
}

// getting the columns that are only active for display
getDisplayingColumns():string[] {
return COLUMN_DEF_DATA.filter(val => val.valid == true ).map(val =>val.label)
}

// getting validity of column
checkValidityOfColumn(i:string):boolean {
return COLUMN_DEF_DATA.filter(val => val.label == i).at(0)!.valid
}

// toggle column validity
toggleColumnValidity(i:string){
COLUMN_DEF_DATA.forEach( col => {
if(col.label == i){
col.valid = !col.valid
}
})
}

4. Final step is to display these into the UI in a reusable manner as well. This is done using the below code:

<!-- Section for the checkbox -->
<div>
<mat-checkbox color="accent" *ngFor="let i of getColumnNames();let j=index" [checked]="checkValidityOfColumn(i)" (change)="toggleColumnValidity(i)">{{i}}</mat-checkbox>
</div>

<!-- Section for the table -->
<table mat-table [dataSource]="newDataSource" class="mat-elevation-z8">
<ng-container matColumnDef="{{col}}" *ngFor="let col of getDisplayingColumns()">
<th mat-header-cell *matHeaderCellDef> {{col}} </th>
<td mat-cell *matCellDef="let element"> {{element[col]}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="getDisplayingColumns()"></tr>
<tr mat-row *matRowDef="let row; columns: getDisplayingColumns();"></tr>
</table>

That’s it and your done! The important advantage of this code would be reusability of the code, any changes on the definition of the table can easily be made just by changing the COLUMN_DEF_DATA variable.

Please like and comment for further convenient coding tricks!! :)

--

--