Angular Material table: Search & Filter

By Arvind Rai, 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 
We assign the filter term to 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;
} 
HTML code:
<input [formControl] = "searchText">
<button (click)="filterTableData()"> Search </button> 
Suppose a table row data is as below.
{id: 101, title: 'Angular Material Tutorial', tech: 'Angular', writtenBy: 'James'} 
To filter the table row for a search text, table row is concatenated by default as below.
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 
A row is displayed for search text only if predicate returns true for that row. By default 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)
    };
} 
In my above table code, I have an array of Article that contains following columns.
article.ts
export interface Article {
    id: number;
    title: string;
    tech: string;
    writtenBy: string;
} 
I am using 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[] 
It is useful to get the set of data that the table is displaying. If our other functions requires the filtered data of the table instead the whole data, we can pass 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);
    }
} 
article.component.html
<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> 
Find the print-screen of the output.
Angular Material table: Search & Filter

5. Reference

6. Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us