Como chamo um pipe Angular 2 com vários argumentos?

204

Eu sei que posso chamar um pipe assim:

{{ myData | date:'fullDate' }}

Aqui, o canal de data leva apenas um argumento. Qual é a sintaxe para chamar um canal com mais parâmetros, do HTML do modelo do componente e diretamente no código?

Eran Shabi
fonte

Respostas:

404

No modelo do seu componente, você pode usar vários argumentos, separando-os com dois pontos:

{{ myData | myPipe: 'arg1':'arg2':'arg3'... }}

No seu código, ele ficará assim:

new MyPipe().transform(myData, arg1, arg2, arg3)

E na sua função de transformação dentro do seu pipe, você pode usar os argumentos como este:

export class MyPipe implements PipeTransform { 
    // specify every argument individually   
    transform(value: any, arg1: any, arg2: any, arg3: any): any { }
    // or use a rest parameter
    transform(value: any, ...args: any[]): any { }
}

Beta 16 e anterior (26-04-2016)

Pipes usam uma matriz que contém todos os argumentos, então você precisa chamá-los assim:

new MyPipe().transform(myData, [arg1, arg2, arg3...])

E sua função de transformação ficará assim:

export class MyPipe implements PipeTransform {    
    transform(value:any, args:any[]):any {
        var arg1 = args[0];
        var arg2 = args[1];
        ...
    }
}
Eran Shabi
fonte
8
Este design é bobo. Eu preciso verificar documento cada vez que me deparo com esta questão
tom10271
Como seria o bit do modelo arg1e se é arg2opcional e você só queria passar arg2?
freethebees
se você passar undefinedcomo o primeiro argumento, ele obterá seu valor padrão.
Eran Chabi
3
hoje em dia, em vez de transform(value:any, arg1:any, arg2:any, arg3:any)usar o operador de resto se sente melhor eu penso:transform(value:any, ...args:any[])
mkb
por que transformar (... args) causa um erro, mas transformar (valor, ... args) não?
Sh eldeeb 22/01
45

Você está perdendo o tubo real.

{{ myData | date:'fullDate' }}

Vários parâmetros podem ser separados por dois pontos (:).

{{ myData | myPipe:'arg1':'arg2':'arg3' }}

Além disso, você pode encadear tubos da seguinte maneira:

{{ myData | date:'fullDate' | myPipe:'arg1':'arg2':'arg3' }}
Eugene
fonte
25

Desde beta.16, os parâmetros não são mais passados ​​como matriz para o transform()método, mas como parâmetros individuais:

{{ myData | date:'fullDate':'arg1':'arg2' }}


export class DatePipe implements PipeTransform {    
  transform(value:any, arg1:any, arg2:any):any {
        ...
}

https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26

Agora, os pipes recebem um número variável de argumentos, e não uma matriz que contém todos os argumentos.

Günter Zöchbauer
fonte
Como seria o bit do modelo arg1e se é arg2opcional e você só queria passar arg2?
freethebees
Podemos usar nomes de variáveis ​​diferentes arg1? Like isFullDate. Estou apenas perguntando porque cada exemplo usa isso.
sabithpocker
'arg1'e 'arg2'são apenas literais de cadeia de caracteres passados ​​como parâmetros adicionais para o canal. Você pode usar qualquer valor ou referência que esteja disponível nesse escopo (a instância atual do componente)
Günter Zöchbauer 12/18
1
@freethebees você tem que passar nulo #
karoluS
O método transform não suporta args de matriz good point @Gunter
BALS 31/10
5

Eu uso Pipes no Angular 2+ para filtrar matrizes de objetos. A seguir, são apresentados vários argumentos de filtro, mas você pode enviar apenas um, se for adequado às suas necessidades. Aqui está um exemplo do StackBlitz . Ele encontrará as chaves pelas quais você deseja filtrar e, em seguida, filtra pelo valor fornecido. Na verdade, é bastante simples; se parece complicado, não é, confira o Exemplo do StackBlitz .

Aqui está o Pipe sendo chamado em uma diretiva * ngFor,

<div *ngFor='let item of items | filtermulti: [{title:"mr"},{last:"jacobs"}]' >
  Hello {{item.first}} !
</div>

Aqui está o Pipe,

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

@Pipe({
  name: 'filtermulti'
})
export class FiltermultiPipe implements PipeTransform {
  transform(myobjects: Array<object>, args?: Array<object>): any {
    if (args && Array.isArray(myobjects)) {
      // copy all objects of original array into new array of objects
      var returnobjects = myobjects;
      // args are the compare oprators provided in the *ngFor directive
      args.forEach(function (filterobj) {
        let filterkey = Object.keys(filterobj)[0];
        let filtervalue = filterobj[filterkey];
        myobjects.forEach(function (objectToFilter) {
          if (objectToFilter[filterkey] != filtervalue && filtervalue != "") {
            // object didn't match a filter value so remove it from array via filter
            returnobjects = returnobjects.filter(obj => obj !== objectToFilter);
          }
        })
      });
      // return new array of objects to *ngFor directive
      return returnobjects;
    }
  }
}

E aqui está o componente que contém o objeto a ser filtrado,

import { Component } from '@angular/core';
import { FiltermultiPipe } from './pipes/filtermulti.pipe';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  items = [{ title: "mr", first: "john", last: "jones" }
   ,{ title: "mr", first: "adrian", last: "jacobs" }
   ,{ title: "mr", first: "lou", last: "jones" }
   ,{ title: "ms", first: "linda", last: "hamilton" }
  ];
}

Exemplo StackBlitz

Exemplo do GitHub: bifurque uma cópia de trabalho deste exemplo aqui

* Observe que, em uma resposta fornecida por Gunter, Gunter afirma que os arrays não são mais usados ​​como interfaces de filtro, mas eu procurei no link que ele fornece e não encontrei nada relacionado a essa afirmação. Além disso, o exemplo StackBlitz fornecido mostra esse código funcionando como pretendido no Angular 6.1.9. Funcionará em Angular 2+.

Happy Coding :-)

user3777549
fonte
Não faz sentido passar uma única matriz com várias entradas em vez de passar vários parâmetros diretamente para o canal.
BrunoJCM
A matriz contém objetos. Os objetos podem conter vários pares de valores-chave usados ​​para criar consultas dinâmicas nas quais você pode procurar registros correspondentes usando nomes de colunas em comparação com os valores de linha da coluna. Você não obteria esse nível de consulta dinâmica passando parâmetros CSV.
User3777549
-2

Estendido de: user3777549

Filtro de valores múltiplos em um conjunto de dados (referência apenas à chave de título)

HTML

<div *ngFor='let item of items | filtermulti: [{title:["mr","ms"]},{first:["john"]}]' >
 Hello {{item.first}} !
</div>

filterMultiple

args.forEach(function (filterobj) {
    console.log(filterobj)
    let filterkey = Object.keys(filterobj)[0];
    let filtervalue = filterobj[filterkey];
    myobjects.forEach(function (objectToFilter) {

      if (!filtervalue.some(x=>x==objectToFilter[filterkey]) && filtervalue != "") {
        // object didn't match a filter value so remove it from array via filter
        returnobjects = returnobjects.filter(obj => obj !== objectToFilter);
      }
    })
  });
Sharan
fonte