2
votes

I am using pipe in my angular Application to filter options values based on search input given by user. This Filter is used at the field level of a form which is dynamically generated using ngFor loop and based on json response.

I am able to use the pipe concept to filter the value for a standalone single input but when I use it multiple times using Ngfor Loop like the below code, It doesn't work perfectly.

 // formdata is coming as of json response from a http request
<div *ngFor="let input1 of formdata.formfields">   


 <mat-select placeholder="Select something" [formControlName]="input1.field_name">
               <ngx-mat-select-search [(ngModel)]="searchText" [ngModelOptions]="{standalone: true}" placeholder="Select {{input1.title}}"></ngx-mat-select-search>

                // here I am using 'fitleroptions' pipe after ngFor and passing searchText ngmodel input binding  

             <mat-option *ngFor="let opt_value of input1.enumNameGroups |  filteroptions : searchText; let i = index" value={{input1.value}}>{{opt_value}}</mat-option>
       </mat-select>

    // other input types like file, text etc....

</div>

This gives me output like this.

enter image description here

Now the problem is that searchText assigned to ngmodel can not be used more then once as it is bounded to only one input and if I do so, it is affecting the other inputs also.

How to pass [(ngmodel)] ="some_variable" and then assign it to filteroptions : "some_variable" so that they are bounded to only one selection input???

So the problem can be also expressed as how to pass dynamic ngmodel name and assign that name to pipe parameters ?

This is the filteroptions pipe I am using .

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'filteroptions'
})
export class FilterOptionsPipe implements PipeTransform {
  transform(items: any[], searchText: string): any[] {
    if(!items) return [];
    if(!searchText) return items;
searchText = searchText.toLowerCase();
return items.filter( it => {

        console.log("got item array here",items);
     return it.toLowerCase().includes(searchText);
    });
   }
}
3
If you ask advice for a pipe, maybe you should post the code of the said pipe ... - user4676340
Hey, thanks for reminding me. I was really missing this code in my own asked question. - Talk is Cheap Show me Code

3 Answers

1
votes

The issue you're seeing is basically due to all ngx-mat-select-search inputs being two-way bound to the same field, searchText. You can easily work around this by introducing a template variable for your filter.

<ngx-mat-select-search ngModel #filter="ngModel" [ngModelOptions]="{standalone: true}" placeholder="Select {{input1.title}}"></ngx-mat-select-search>
<mat-option *ngFor="let opt_value of input1.enumNameGroups |  filteroptions : filter.value; let i = index" value={{input1.value}}>{{opt_value}}</mat-option>
1
votes
<mat-select 
 placeholder="Owner" 
 [(ngModel)]="criteriaOwner" 
 name="ownerId" 
 required>
 <ngx-mat-select-search ngModel 
    #filter="ngModel" 
    [ngModelOptions]="{standalone: true}" 
    [placeholderLabel]="'Find owner...'" 
    [noEntriesFoundLabel]="'No matching owner found'" >
 </ngx-mat-select-search>
    <mat-option *ngFor="let item of criteriaOwners | filterByProperty: 
      ['name',filter.value]; let i = index" [value]="item">
        <div fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
            <div>
                {{item.name}}
            </div>
        </div>
    </mat-option>
</mat-select>

/*Write pipe like below.*/

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

@Pipe({
  name: 'filterByProperty'
})
export class FilterByPropertyPipe implements PipeTransform {

  transform(list: any[], args?: any): any {
    if (!list || !args) {
      return list;
    }

    var columnName = args[0];
    var columnValue = args[1];

    return list.filter(listItem => ('' + listItem[columnName]).toLocaleLowerCase().indexOf(columnValue.toString().toLocaleLowerCase()) !== -1);
  }

}
0
votes

HTML

<input [(ngModel)]="searchText">
<div *ngFor="let item of items | searchFilter:'id,name':searchText">{{item.name}}</div>

pipeFilter.ts

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

@Pipe({
  name: 'searchFilter'
})

export class SearchFilterPipe implements PipeTransform {
  public transform(value, keys: string, term: string) {

    if (!term) return value;
    return (value || []).filter(x => keys.split(',').some(key => x.hasOwnProperty(key) && new RegExp(term, 'gi').test(x[key])));

  }
}