1

I want to write a generic filter in angular 7 to perform search filter operation on any field in any number of screens. I have found some links suggesting writing custom pipe filters but they always filter based on particular static field.

To explain more, I have around 20 screens in my project. Each screen is making an API call , fetching data and displaying on the UI ,like one is device screen showing data for fields:

deviceId, deviceHardwareNumber, deviceSoftwareNumber, deviceVendor, devicePurchaseDate

Another screen for deviceServiceDetails

deviceId, deviceServiceProvider, deviceServiceDate, nextServiceDueDate

Now either I can write 20 filters for 20 screens for filtering on different field names or is there any way possible for writing only one filter for all the screens and filtering on any field.

Is there a way to make it dynamic by writing one filter irrespective of the number of screens, i.e. any list or searchText passed from any screen should be filtered and returned?

Vadim Landa
  • 2,784
  • 5
  • 23
  • 33
Tarun
  • 271
  • 1
  • 6
  • 18
  • Can you provide more details? What is the list of data you would like to filter from? – wentjun Mar 26 '19 at 06:56
  • Edited the question to add in more details – Tarun Mar 26 '19 at 07:02
  • Oh, alright, so it is something like filtering through an array of objects, but with dynamic filtering? – wentjun Mar 26 '19 at 07:04
  • Yes , I want to filter through the array of objects being displayed on UI using ngFor but with dyanamic filtering – Tarun Mar 26 '19 at 07:12
  • I explained how to do it here. It works. https://stackoverflow.com/questions/55060545/angular-search-bar-in-typescript-table/55061017#55061017 – Jon Fernandez Mar 26 '19 at 07:17
  • 2
    So you want to do exactly what the official Angular documentation recommends not to do? https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe – JB Nizet Mar 26 '19 at 07:17

2 Answers2

2

It 's hard to create a filter to handle every case scenario but I did something to handle string value and with option to enter the property name in that case I manage to use this filter in many screens , but you can see if you want to handle another type you may need to create a new filter in that case

In case of filter a string property with support different method like include , equal and not equal

string filter pipe

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

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {

  transform(arr: any[], prop: string, value: string , method:Method): any {
    if (arr) {
      if (!value) {
        return arr
      } else {
        return arr.filter(obj => this.filter(obj[prop],value, method))
      }
    } else {
      return []
    }
  }

  filter(source :string, target :string, method:Method) : boolean {

    switch(method) {
      case "includes" : return source.includes(target)
      case "equal"  : return source === target
      case "not-equal" : return source !== target
    }
  }
}

type Method ="includes" | "equal" | "not-equal"

template

<p>
Include <br>
 <input type="text" placeholder="search..." [(ngModel)]="searchValue">
</p>

<div *ngFor="let skill of skills | filter :'name' : searchValue: 'includes' ">
  {{skill.name}}
</div> 


<p>
Equal <br>
 <input type="text" placeholder="search..." [(ngModel)]="searchValue02">
</p>

<div *ngFor="let skill of skills | filter :'name' : searchValue02 : 'equal'">
  {{skill.name}}
</div> 

Demo

Muhammed Albarmavi
  • 23,240
  • 8
  • 66
  • 91
0

You can also use Regex instead of includes() to get case in-sensitive filter results.

case "includes" : return source.includes(target); Case Sensitive

case "includes" : return new RegExp(target, "i").test(source); Case Insensitive

Hope it helps!

Vino
  • 1
  • 1