Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter on multiple columns using one pipe angular 2

I am trying to filter Array data based on multiple columns using only one Pipe. Right now, It filters first column value. Please check my below code and help me to sort this out.

My Code:

@Pipe({ name: "dataFilter", pure: false })
export class DataFilterPipe implements PipeTransform {
    transform(value: Array<any>, filter: any[]) {
        if (!filter) {
            return value;
        } else if (value) {
            return value.filter(item => {
                for (var i = 0; i < filter.length; i++) {
                    if (filter[i][1] == undefined) {
                        return true;
                    } else if ((typeof item[filter[i][0]] === 'string' || item[filter[i][0]] instanceof String) &&
                        (item[filter[i][0]].toLowerCase().indexOf(filter[i][1]) !== -1)) {
                        return true;
                    }
                    return false;
                }
            });
        }
    }
}

I am passing data like dataFilter : [['column1',value1],['column2',value2],['column3',value3]].

like image 759
Jeeten Parmar Avatar asked Jan 16 '17 08:01

Jeeten Parmar


2 Answers

Here is a solution using the object passed as multiple columns filter. I found it more convenient then passing a 2D array:

    @Pipe({         name: 'filter'     })     export class FilterPipe implements PipeTransform {         transform(items: Array<any>, filter: {[key: string]: any }): Array<any> {             return items.filter(item => {                 const notMatchingField = Object.keys(filter)                                              .find(key => item[key] !== filter[key]);                  return !notMatchingField; // true if matches all fields             });         }     } 

Having an array of objects with multiple columns:

this.people = [   {name: 'John', age: 27, sex: 'male'},   {name: 'Lara', age: 21, sex: 'female'},   {name: 'Rick', age: 29, sex: 'male'},   {name: 'Eva',  age: 27, sex: 'female'},   {name: 'Mike', age: 27, sex: 'male'} ]; 

And a filter:

this.peopleFilter = {age: 27, sex: 'male'}; 

Use it like:

 <div *ngFor="let person of people | filter: peopleFilter;"></div> 

As a result, two people are matching our criteria: John and Mike.

Here is the working plunker: Multiple columns filter pipe demo.

like image 158
seidme Avatar answered Sep 20 '22 13:09

seidme


Here is what I did with Angular 8:

Goal: Search on multiple properties say "Property1" and "Property2" from a list of items for a given keyword:

app.module.ts:

......
import { MyFilterPipe } from './shared/pipes/my-filter.pipe';

@NgModule({
  declarations: [
    ...
    MyFilterPipe
  ],
  imports: [
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Pipe: content-filter.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'myFilter'
})
export class MyFilterPipe implements PipeTransform {

  transform(items: any[], keyword: any, properties: string[]): any[] {
    if (!items) return [];
    if (!keyword) return items;
    debugger;
    return items.filter(item => {
      var itemFound: Boolean;
      for (let i = 0; i < properties.length; i++) {
        if (item[properties[i]].toLowerCase().indexOf(keyword.toLowerCase()) !== -1) {
          itemFound = true;
          break;
        }
      }
      return itemFound;
    });

  }
}

component:

<input type="search" class="form-control filter-list-input" placeholder="Filter"
                  aria-label="Filter" name="search" [(ngModel)]="searchText" >

    <div *ngFor="let itemof myItems | myFilter:searchText:['Property1', 'Property2']; let i = index">...
</div>

component.ts:

export class MyListComponent implements OnInit {

  ...
  searchText: string;
like image 36
Raghav Avatar answered Sep 17 '22 13:09

Raghav