Passando argumentos para filtros angularjs

99

É possível passar um argumento para a função de filtro para que você possa filtrar por qualquer nome?

Algo como

$scope.weDontLike = function(item, name) {
    console.log(arguments);
    return item.name != name;
};
metamorfo
fonte

Respostas:

223

Na verdade, há outra (solução talvez melhor) onde você pode usar o filtro 'filtro' nativo do angular e ainda passar argumentos para o seu filtro personalizado.

Considere o seguinte código:

<div ng-repeat="group in groups">
    <li ng-repeat="friend in friends | filter:weDontLike(group.enemy.name)">
        <span>{{friend.name}}</span>
    <li>
</div>

Para fazer isso funcionar, você apenas define seu filtro da seguinte forma:

$scope.weDontLike = function(name) {
    return function(friend) {
        return friend.name != name;
    }
}

Como você pode ver aqui, weDontLike na verdade retorna outra função que tem o seu parâmetro em seu escopo, bem como o item original proveniente do filtro.

Levei 2 dias para perceber que você pode fazer isso, ainda não vi essa solução em lugar nenhum.

Caixa inversão de polaridade de um filtro angularjs para ver como você pode usar isso para outras operações úteis com filtro.

Denis Pshenov
fonte
Caso seu filtro precise de vários argumentos, consulte Como chamo um filtro Angular.js com vários argumentos?
nh2
Esse método também resolveu um problema estranho em que dentro do ng-repeat eu não conseguia passar meus próprios parâmetros para o meu filtro. Não importa o que eu fizesse, eles continuavam voltando como o índice e a coleção geral. Ao fazer esse método de retorno, consegui passar meus parâmetros e ainda carregar o elemento original, ótima correção!
Dennis Smolek
Essa resposta resolveu meu problema de não conseguir passar uma variável $ scope como parâmetro para a função de filtro. Melhor solução. Votado!
valafar
Se eu pudesse votar a favor mais de uma vez, teria certeza de que seria a resposta mais votada da história do SO. Isso tem me incomodado muito há anos ... e então encontro a resposta (agora com 2 anos) ... Muito obrigado.
PKD
Ainda útil em 2019! Muito obrigado.
ashilon
76

Pelo que entendi você não pode passar argumentos para uma função de filtro (ao usar o filtro 'filtro'). O que você teria que fazer é escrever um filtro personalizado, parecido com este:

.filter('weDontLike', function(){

return function(items, name){

    var arrayToReturn = [];        
    for (var i=0; i<items.length; i++){
        if (items[i].name != name) {
            arrayToReturn.push(items[i]);
        }
    }

    return arrayToReturn;
};

Aqui está o jsFiddle funcional: http://jsfiddle.net/pkozlowski_opensource/myr4a/1/

A outra alternativa simples, sem escrever filtros personalizados, é armazenar um nome para filtrar em um escopo e, em seguida, escrever:

$scope.weDontLike = function(item) {
  return item.name != $scope.name;
};
pkozlowski.opensource
fonte
Isso é prefeito obrigado! Armazenar o nome no escopo não funcionará tão bem, pois tenho três listas dos mesmos dados na mesma página im filtrando com diferentes estados (ou nomes).
metamorfo de
algum para definir 'Adam' (referindo-se ao seu JSFiddle) dinamicamente? parece impossível (e acho que é propositalmente) combinar o ngModel e um filtro personalizado no Angular ...
Rolf
É possível reordenar os parâmetros de um filtro? Por exemplo, passa o item para o segundo parâmetro de um filtro?
Pooya
É importante notar que neste exemplo a marcação é {{items | weDontLike: 'thenameyoudontlike'}} ... agora você tem que ir ao violino para conseguir isso. Também vale a pena notar que você pode passar vários parâmetros para o seu filtro personalizado {{itens | weDontLike: 'thename': ['Eu sou', 'um array']: 'e assim por diante'}} você apenas adicionaria mais argumentos ao seu filtro personalizado para ter acesso a eles.
Benjamin Conant
62

Na verdade você pode passar um parâmetro ( http://docs.angularjs.org/api/ng.filter:filter ) e não precisa de uma função customizada apenas para isso. Se você reescrever seu HTML como a seguir, funcionará:

<div ng:app>
 <div ng-controller="HelloCntl">
 <ul>
    <li ng-repeat="friend in friends | filter:{name:'!Adam'}">
        <span>{{friend.name}}</span>
        <span>{{friend.phone}}</span>
    </li>
 </ul>
 </div>
</div>

http://jsfiddle.net/ZfGx4/59/

mikel
fonte
8
Sim. Nota lateral - se o nome de alguém é '! Adam', você o pega como {name: '!! Adam'}.
honzajde
5
Você também pode passar matrizes aqui também como estefilter:['Adam', 'john']
iConnor
6
O link jsfiddle está quebrado.
Seregwethrin
4
! Adam é o pior nome de todos
Ben Wheeler
6
Não-Não-Adam é obviamente pior.
twip de
30

Você pode simplesmente fazer assim No modelo

<span ng-cloak>{{amount |firstFiler:'firstArgument':'secondArgument' }}</span>

No filtro

angular.module("app")
.filter("firstFiler",function(){

    console.log("filter loads");
    return function(items, firstArgument,secondArgument){
        console.log("item is ",items); // it is value upon which you have to filter
        console.log("firstArgument is ",firstArgument);
        console.log("secondArgument ",secondArgument);

        return "hello";
    }
    });
abhaygarg12493
fonte
Esta é a melhor resposta. Funciona com objetos dinâmicos. Esta deve ser a resposta aceita.
abelabbesnabi
2

Estendendo a resposta de pkozlowski.opensource e usando o array'smétodo de filtro embutido javascript , uma solução aprimorada poderia ser esta:

.filter('weDontLike', function(){
    return function(items, name){
        return items.filter(function(item) {
            return item.name != name;
        });
    };
});

Aqui está o link jsfiddle .

Mais sobre o filtro Array aqui .

Nasif Md. Tanjim
fonte
1

Você pode passar vários argumentos para o filtro angular!

Definindo meu aplicativo angular e uma variável de nível de aplicativo -

var app = angular.module('filterApp',[]);
app.value('test_obj', {'TEST' : 'test be check se'});

Seu filtro será como: -

app.filter('testFilter', [ 'test_obj', function(test_obj) {
    function test_filter_function(key, dynamic_data) {
      if(dynamic_data){
        var temp = test_obj[key]; 
        for(var property in dynamic_data){
            temp = temp.replace(property, dynamic_data[property]);
        }
        return temp;
      }
      else{
        return test_obj[key] || key;
      }

    }
    test_filter_function.$stateful = true;
    return test_filter_function;
  }]);

E de HTML você enviará dados como: -

<span ng-bind="'TEST' | testFilter: { 'be': val, 'se': value2 }"></span>

Aqui estou enviando um objeto JSON para o filtro. Você também pode enviar qualquer tipo de dados como string ou número.

também você pode passar um número dinâmico de argumentos para filtrar; nesse caso, você deve usar argumentos para obter esses argumentos.

Para uma demonstração de trabalho, vá aqui - passando vários argumentos para o filtro angular

Partha Roy
fonte
0

Você pode simplesmente usar | filter:yourFunction:arg

<div ng-repeat="group in groups | filter:weDontLike:group">...</div>

E em js

$scope.weDontLike = function(group) {
//here your condition/criteria
return !!group 
}
user2972221
fonte