Pesquisa de site

typescript - Como usar este pipe no Angular 5 dinamicamente?


Estou usando pipe na minha aplicação Angular para filtrar valores de opções com base na entrada de pesquisa fornecida pelo usuário. Este filtro é usado no nível do campo de um formulário que é gerado dinamicamente usando o loop ngFor e baseado na resposta JSON.

Sou capaz de usar o conceito de pipe para filtrar o valor de uma entrada única independente, mas quando o uso várias vezes usando o loop NgFor como no código abaixo, ele não funciona perfeitamente.

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

Isso me dá uma saída assim.

Agora o problema é que searchText atribuído ao ngmodel não pode ser usado mais de uma vez, pois está vinculado a apenas um input e, se eu fizer isso, também afetará os outros inputs.

Como passar [(ngmodel)] ="some_variable" e depois atribuí-lo a filteroptions: "some_variable" para que eles estejam vinculados a apenas uma entrada de seleção???

Então, o problema também pode ser expresso como como passar um nome dynamic ngmodel e atribuir esse nome aos parâmetros do pipe?

Este é o pipe filteroptions que estou usando.

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);
    });
   }
}

Resposta #1

O problema que você está vendo é basicamente devido a todos os inputs ngx-mat-select-search estarem vinculados bidirecionalmente ao mesmo campo, searchText. Você pode contornar isso facilmente introduzindo uma variável de template para o seu filtro.

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

Resposta #2

<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);
  }

}