Multiple Filters on MatTable

In Angular Material Tables, you can add multi colum filter using filterPredicate property on mat-tables and providing them a customFilter method as shown below

Source Link

Demo Link

enter image description here

        ngOnInit() {

        // Overrride default filter behaviour of Material Datatable
        this.dataSource.filterPredicate = this.createFilter();
        }

        ...
        ...

        // Custom filter method fot Angular Material Datatable
        createFilter() {
        let filterFunction = function (data: any, filter: string): boolean {
          let searchTerms = JSON.parse(filter);
          let isFilterSet = false;
          for (const col in searchTerms) {
            if (searchTerms[col].toString() !== '') {
              isFilterSet = true;
            } else {
              delete searchTerms[col];
            }
          }

          let nameSearch = () => {
            let found = false;
            if (isFilterSet) {
              for (const col in searchTerms) {
                searchTerms[col].trim().toLowerCase().split(' ').forEach(word => {
                  if (data[col].toString().toLowerCase().indexOf(word) != -1 && isFilterSet) {
                    found = true
                  }
                });
              }
              return found
            } else {
              return true;
            }
          }
          return nameSearch()
        }
        return filterFunction
        }

I think you just forgot to call toLowerCase() for searchString.name

data.name.toString().trim().toLowerCase().indexOf(searchString.name.toLowerCase())!== -1;


EDIT: One approach is to create a global filter field in your Component class.

globalFilter = '';

<mat-form-field>
  <input matInput [ngModel]="globalFilter" (ngModelChange)="applyFilter($event)" placeholder="Filter">
</mat-form-field>

applyFilter(filter) {
    this.globalFilter = filter;
    this.dataSource.filter = JSON.stringify(this.filteredValues);
}

Then try to filter using global filter first before the other fields.

  customFilterPredicate() {
    const myFilterPredicate = (data: PeriodicElement, filter: string): boolean => {
      var globalMatch = !this.globalFilter;

      if (this.globalFilter) {
        // search all text fields
        globalMatch = data.name.toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1;
      }

      if (!globalMatch) {
        return;
      }

      let searchString = JSON.parse(filter);
      return data.position.toString().trim().indexOf(searchString.position) !== -1 &&
        data.name.toString().trim().toLowerCase().indexOf(searchString.name.toLowerCase()) !== -1;
    }
    return myFilterPredicate;
  }

Here's the working app: https://stackblitz.com/edit/angular-hbakxo-5jeaic