Filtering specific column in Angular Material table in angular 5

前端 未结 8 701
太阳男子
太阳男子 2020-12-01 07:11

In Angular material official website it is mentioned that filterPredicate: ((data: T, filter: string) => boolean) will filter data based on specific field. But don\'t gettin

相关标签:
8条回答
  • 2020-12-01 07:20

    Working filters on each column, demo link Stackblitz.

    To filter specific column in mat-table, add a search field for the column as below;

    <mat-form-field class="filter" floatLabel="never">
        <mat-label>Search</mat-label>
        <input matInput [formControl]="nameFilter">
      </mat-form-field>
    

    And we connect the inputs to FormControls from the ReactiveFormsModule.

        filterValues = {
        name: '',
        id: '',
        colour: '',
        pet: ''
     };
    

    And we will watch the value of the filter inputs and modify this filter object and the data source’s filter property when they change. We must assign the stringified version of the filter object to the data source’s filter property

        ngOnInit() {
        this.nameFilter.valueChanges
          .subscribe(
            name => {
              this.filterValues.name = name;
              this.dataSource.filter = JSON.stringify(this.filterValues);
            }
          )
        this.idFilter.valueChanges
          .subscribe(
            id => {
              this.filterValues.id = id;
              this.dataSource.filter = JSON.stringify(this.filterValues);
            }
          )
        this.colourFilter.valueChanges
          .subscribe(
            colour => {
              this.filterValues.colour = colour;
              this.dataSource.filter = JSON.stringify(this.filterValues);
            }
          )
        this.petFilter.valueChanges
          .subscribe(
            pet => {
              this.filterValues.pet = pet;
              this.dataSource.filter = JSON.stringify(this.filterValues);
            }
          )
      }
    

    We have to change the data source’s filterPredicate to tell it how to interpret the filter information.

        constructor() {
        this.dataSource.data = this.people;
        this.dataSource.filterPredicate = this.tableFilter();
        }
    
        tableFilter(): (data: any, filter: string) => boolean {
        let filterFunction = function(data, filter): boolean {
          let searchTerms = JSON.parse(filter);
          return data.name.toLowerCase().indexOf(searchTerms.name) !== -1
            && data.id.toString().toLowerCase().indexOf(searchTerms.id) !== -1
            && data.colour.toLowerCase().indexOf(searchTerms.colour) !== -1
            && data.pet.toLowerCase().indexOf(searchTerms.pet) !== -1;
        }
        return filterFunction;
    }
     
    
    0 讨论(0)
  • 2020-12-01 07:25

    Just declare a function with the following declaration in your component and then assign it to DataSource.filterPredicate. To use the filter just assign a string to DataSource.filter property.

      customFilter(Data: T, Filter: string): boolean {
        return <true if Data matches filter>
      }
    
    0 讨论(0)
  • 2020-12-01 07:27

    If you are looking for a range predicate to filter out a range of values on one attribute:

    applyRangePredicate() {
      this.datasource.filterPredicate = (data:
        {id: string}, filter: string) => {
          let searchlist = JSON.parse(filter);
          var found = false
          searchlist.forEach(item => {
            if (data.id.indexOf(item) !== -1)
              found = true 
          })
          return found
        }
      }
    

    then assign a json string to stream filtered data to the UI

    this.applyRangePredicate()    
    this.datasource.filter = JSON.stringify(string[])
    
    0 讨论(0)
  • 2020-12-01 07:28

    To expand on Naresh's answer, the following HTML snippet shows how to get both sorting and filtering in the same column and also the little "x" button to clear filter terms:

       <ng-container matColumnDef="description">
        <th mat-header-cell  *matHeaderCellDef mat-sort-header>
          <mat-form-field >
            <mat-label>Search Description</mat-label>
            <input matInput 
                   [formControl]="descriptionFilter" 
                   (click)="$event.stopPropagation()">
            <button mat-button 
                    *ngIf="descriptionFilter.value" 
                    matSuffix mat-icon-button 
                    aria-label="Clear" 
                    (click)="descriptionFilter.setValue('')">
              <mat-icon>close</mat-icon>
            </button>
          </mat-form-field>
        </th>
    
        <td mat-cell *matCellDef="let assessment">
          {{assessment?.description}} </td>
      </ng-container>
    
    0 讨论(0)
  • 2020-12-01 07:30

    You have to override the filterPredicate of your dataSource.

    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(data.symbol.toLowerCase().includes(filter) || data.position.toString().includes(filter);
    };
    
    0 讨论(0)
  • 2020-12-01 07:34

    Use filterPredicate to override filter logic using customFilter()

    Demo Link

    Source Link

            ...
            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
            }
    
    0 讨论(0)
提交回复
热议问题