Angular Material table: Search & Filter
April 14, 2024
On this page we will learn to enable search and customize default filter for our material table in our Angular Material application.
Angular Material provides
MatTableDataSource
to display, filter, sort and paginate the table data. To enable filter, we need to use its following properties.
filter: Accepts search text to filter table data. We can use
FormControl
or NgModel
to access search text from input text element entered by user.
filterPredicate: Use this to customize default filter, for example, to search the user text only in selected columns.
filteredData: Access the set of filtered rows. We can pass it to other functions for any other data processing.
Now let us discuss searching and filtering material table in detail.
1. Enable Default Search: Use filter
only
filter
is a property of MatTableDataSource
and declared as below.
filter: string
filter
property that is used to filter the table row. It is used as below.
TS code:
const tableData = <table_data_array>; dataSource = new MatTableDataSource(tableData); searchText = new FormControl(); filterTableData() { this.dataSource.filter = this.searchText.value; }
<input [formControl] = "searchText"> <button (click)="filterTableData()"> Search </button>
{id: 101, title: 'Angular Material Tutorial', tech: 'Angular', writtenBy: 'James'}
101Angular Material TutorialAngularJames
Then it is checked if the concatenated string contains the search text.
To search table column wise, we need to customize the filter using
filterPredicate
.
By default, rows are filtered searching the search text in the concatenated string of columns with case-insensitive.
2. Custom Search: Use filterPredicate
with filter
Use filterPredicate
to change default filter strategy. Find its declaration.
filterPredicate: (data: T, filter: string) => boolean
filterPredicate
concatenates the row object and returns true if concatenated string contains the search text with case-insensitive.
To customize this behaviour, we can define
filterPredicate
and use filter
property to assign search text. Suppose we want to filter row only on the basis of a column, then use filterPredicate
as below.
filterTableData() { this.dataSource.filter = this.searchText.value; this.dataSource.filterPredicate = (data: Article, filter: string) => { return data.title.includes(filter) }; }
Article
that contains following columns.
article.ts
export interface Article { id: number; title: string; tech: string; writtenBy: string; }
title
column to filter data.
3. Access filtered data using filteredData
filteredData
is an array that contains those table rows which are obtained by filtering table data for a search text. Find its declaration.
filteredData: T[]
filteredData
to that function.
Find the code snippet.
filterTableData() { this.dataSource.filter = "<search_text>"; const filteredRows = this.dataSource.filteredData; console.log(filteredRows); }
filteredRows
contains only those rows that contains the specified search text.
4. Example: Filter By Column
In our demo application, We have a text input for default search and four more search input text to filter rows by columns.article.component.ts
import { Component, AfterViewInit, ViewChild } from '@angular/core'; import { ArticleService } from './article.service'; import { MatTableDataSource, MatTableModule, } from '@angular/material/table'; import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; import { MatSort, MatSortModule } from '@angular/material/sort'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { Article } from './article'; @Component({ selector: 'app-article', standalone: true, imports: [MatTableModule, MatSortModule, MatPaginatorModule, ReactiveFormsModule], templateUrl: './article.component.html' }) export class ArticleComponent implements AfterViewInit { @ViewChild(MatSort) sort = {} as MatSort; @ViewChild(MatPaginator) paginator = {} as MatPaginator; searchText = new FormControl(); id = new FormControl(); title = new FormControl(); tech = new FormControl(); writer = new FormControl(); constructor(private artlService: ArticleService) { } displayedColumns: string[] = ['id', 'title', 'tech', 'writtenBy']; dataSource = new MatTableDataSource(this.artlService.getArticles()); ngAfterViewInit() { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; } defaultSearch() { this.dataSource.filter = this.searchText.value; const filteredRows = this.dataSource.filteredData; console.log(filteredRows); } filterById() { this.dataSource.filter = this.id.value; this.dataSource.filterPredicate = (article: Article, searchText: string) => { return article.id.toString() === searchText; }; const filteredRows = this.dataSource.filteredData; console.log(filteredRows); } filterByTitle() { this.dataSource.filter = this.title.value; this.dataSource.filterPredicate = (article: Article, searchText: string) => { return article.title.includes(searchText) }; const filteredRows = this.dataSource.filteredData; console.log(filteredRows); } filterByTech() { this.dataSource.filter = this.tech.value; this.dataSource.filterPredicate = (article: Article, searchText: string) => { return article.tech.includes(searchText) }; const filteredRows = this.dataSource.filteredData; console.log(filteredRows); } filterByWriter() { this.dataSource.filter = this.writer.value; this.dataSource.filterPredicate = (article: Article, searchText: string) => { return article.writtenBy.includes(searchText) }; const filteredRows = this.dataSource.filteredData; console.log(filteredRows); } }
<input [formControl]="searchText"> <button (click)="defaultSearch()"> Default Search </button><br /><br /> <input [formControl]="id"> <button (click)="filterById()"> Filter By Id </button> | <input [formControl]="title"> <button (click)="filterByTitle()"> Filter By Title </button> | <input [formControl]="tech"> <button (click)="filterByTech()"> Filter By Tech </button> | <input [formControl]="writer"> <button (click)="filterByWriter()"> Filter By Writer </button> <div class="mat-elevation-z8"> <table mat-table [dataSource]="dataSource" matSort> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th> <td mat-cell *matCellDef="let element"> {{element.id}} </td> </ng-container> <ng-container matColumnDef="title"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Title </th> <td mat-cell *matCellDef="let element"> {{element.title}} </td> </ng-container> <ng-container matColumnDef="tech"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Technology </th> <td mat-cell *matCellDef="let element"> {{element.tech}} </td> </ng-container> <ng-container matColumnDef="writtenBy"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Written By </th> <td mat-cell *matCellDef="let element"> {{element.writtenBy}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator [pageSizeOptions]="[5, 8, 15]" showFirstLastButtons></mat-paginator> </div>