Filtering specific column in Angular Material Tabl

2020-07-02 09:22发布

I am using mat-table. It has a filter which works fine.

Filter happened against this below data (All columns)

const ELEMENT_DATA: Element[] = [
  {position: 14598, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 24220, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 39635, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 42027, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
  {position: 53216, name: 'Boron', weight: 10.811, symbol: 'B'},
  {position: 60987, name: 'Carbon', weight: 12.0107, symbol: 'C'},
  {position: 70976, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
  {position: 81297, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
  {position: 90975, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
  {position: 18879, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
  {position: 11209, name: 'Sodium', weight: 22.9897, symbol: 'Na'}

];

But Now I am trying to change the filter because I want is filter just for "position", "name", "symbol" column. I have gone through this example but Filtering specific column in Angular Material table in angular 5.

I did not understand please help me on this

StackBlitz Code

4条回答
够拽才男人
2楼-- · 2020-07-02 09:48

Material has implemented its own search feature you can override it by updating the filterPredicate property on the date source. Call the generateTable function on ngOninit() life cycle.

generateTable(tableData: any) {
    this.dataSource = new MatTableDataSource(tableData);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
    this.dataSource.filterPredicate = (data: any, filter: string) => {
      console.log(data);
      console.log(filter);
      let matchFound = false;
      for (let column of this.displayedColumns) {
        if(column in data) {
          if(data[column]) {
            matchFound = (matchFound || data[column].toString().trim().toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1)
          }
        }
      }
      return matchFound;
    }
  }

Whenever you wish to apply the filter, update the filter property on dataSource to the string value to be searched.

applyFilter(searchValue: any) {
    this.dataSource.filter = this.filterText.trim().toLowerCase();
    }
查看更多
萌系小妹纸
3楼-- · 2020-07-02 09:52

You have to override the filterPredicate of your dataSource.

Here's an example of how to do it: Working demo


Essentially, you want to specify what properties in your data the filter is applied to:

this.dataSource.filterPredicate = function(data, filter: string): boolean {
    return data.name.toLowerCase().includes(filter) || data.symbol.toLowerCase().includes(filter) || data.position.toString().includes(filter);
};
查看更多
Summer. ? 凉城
4楼-- · 2020-07-02 10:00

Adding to bugs' answer. Here's a more elaborate implementation,

export class FilterTable implements AfterViewInit {
  //some datasource
  datasource //=
  displayedColumns //=insert column names on which you want to filter whether they are displayed or not, but present in the datasource

  // Apply filter to the datasource
  applyFilter(filterValue: string) {
    this.datasource.filter = filterValue;
  }


  ngAfterViewInit() {
    // Overwriting filterPredicate here, as it needs to be done after the datasource is loaded.
    this.datasource.filterPredicate = (data, filter) => {
      var tot = false;
      for (let column of this.displayedColumns) {
        //incase if there is a date type and is displayed differently using a pipe, then convert it intorequired format before filtering
        //check if all the columnson which you are filtering are actually present
        if ((column in data) && (new Date(data[column].toString()).toString() == "Invalid Date")) {
          //if not date column
          tot = (tot || data[column].toString().trim().toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1);
        } else {
          //change this to the format in which date is displayed
          var date = new Date(data[column].toString());
          var m = date.toDateString().slice(4, 7) + " " + date.getDate() + " " + date.getFullYear();
          tot = (tot || m.toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1);
        }
      }
      return tot;
    }
  }
}

Please feel free to suggest edits, if this could be improved

查看更多
beautiful°
5楼-- · 2020-07-02 10:01

In Angular Material Tables, we can create column based filters from data itself.

Source Link

Demo Link

enter image description here

For that, we need to override the filterPredicate method with customFilter() method

        ...
        ngOnInit() {
            this.getRemoteData();

            // 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
        }

Check complete working code here

查看更多
登录 后发表回答