Pasando argumentos a los filtros de angularjs

99

¿Es posible pasar un argumento a la función de filtro para que pueda filtrar por cualquier nombre?

Algo como

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

Respuestas:

223

En realidad, hay otra (tal vez una mejor solución) donde puede usar el filtro de 'filtro' nativo de angular y aún pasar argumentos a su filtro personalizado.

Considere el siguiente 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 que esto funcione, simplemente defina su filtro de la siguiente manera:

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

Como puede ver aquí, weDontLike en realidad devuelve otra función que tiene su parámetro en su alcance, así como el elemento original que proviene del filtro.

Me tomó 2 días darme cuenta de que puedes hacer esto, todavía no he visto esta solución en ningún lado.

Pedido polaridad inversa de un filtro angularjs para ver cómo se puede utilizar esto para otras operaciones útiles con filtro.

Denis Pshenov
fuente
En caso de que su filtro necesite varios argumentos, consulte ¿Cómo llamo a un filtro Angular.js con varios argumentos?
nh2
Este método también resolvió un problema extraño en el que dentro de ng-repeat no podía pasar mis propios parámetros a mi filtro. No importa lo que hice, seguían apareciendo como el índice y la colección general. Al hacer este método de retorno, pude pasar mis parámetros y aún cargar el elemento original, ¡gran solución!
Dennis Smolek
Esta respuesta resolvió mi problema en el que no pude pasar una variable $ scope como parámetro a la función de filtro. Mejor solución. ¡Voto a favor!
valafar
Si pudiera votar a favor de esto más de una vez, me aseguraría de que fuera la respuesta más votada en la historia de SO. Esto me ha estado molestando durante años ... y luego encuentro la respuesta (ahora de 2 años) ... Muchísimas gracias.
PKD
¡Sigue siendo útil en 2019! Muchas gracias.
ashilon
76

Por lo que tengo entendido, no puede pasar argumentos a una función de filtro (cuando se usa el filtro de 'filtro'). Lo que tendría que hacer es escribir un filtro personalizado, algo como esto:

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

Aquí está el jsFiddle de trabajo: http://jsfiddle.net/pkozlowski_opensource/myr4a/1/

La otra alternativa simple, sin escribir filtros personalizados, es almacenar un nombre para filtrar en un alcance y luego escribir:

$scope.weDontLike = function(item) {
  return item.name != $scope.name;
};
pkozlowski.opensource
fuente
¡Eso es prefecto gracias! Almacenar el nombre en el alcance no funcionará tan bien ya que tengo tres listas de los mismos datos en la misma página y estoy filtrando con diferentes estados (o nombres).
cambiaformas
any para establecer 'Adam' (refiriéndose a su JSFiddle) dinámicamente? parece imposible (y supongo que es a propósito) combinar ngModel y un filtro personalizado en Angular ...
Rolf
¿Es posible reordenar los parámetros de un filtro? Por ejemplo, ¿pasar el elemento al segundo parámetro de un filtro?
Pooya
Vale la pena señalar que en este ejemplo el marcado es {{items | weDontLike: 'thenameyoudontlike'}} ... ahora mismo tienes que ir al violín para conseguir eso. También vale la pena señalar que puede pasar varios parámetros a su filtro personalizado {{elementos | weDontLike: 'thename': ['Yo soy', 'una matriz']: 'y así sucesivamente'}} simplemente agregaría más argumentos a su filtro personalizado para tener acceso a ellos.
Benjamin Conant
62

En realidad, puede pasar un parámetro ( http://docs.angularjs.org/api/ng.filter:filter ) y no necesita una función personalizada solo para esto. Si reescribe su HTML como se muestra a continuación, 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
fuente
8
Si. Nota al margen: si el nombre de alguien es '! Adam', lo obtienes como {name: '!! Adam'}.
honzajde
5
También puede pasar matrices aquí también de esta manerafilter:['Adam', 'john']
iConnor
6
El enlace jsfiddle está roto.
Seregwethrin
4
! Adam es el peor nombre de todos los tiempos
Ben Wheeler
6
Not-Not-Adam es obviamente peor.
twip
30

Simplemente puede hacer esto en la plantilla

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

En 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
fuente
Esta es la mejor respuesta. Funciona con objetos dinámicos. Esta debería ser la respuesta aceptada.
abelabbesnabi
2

Ampliando la respuesta de pkozlowski.opensource y usando el array'smétodo de filtro incorporado de JavaScript , una solución embellecida podría ser esta:

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

Aquí está el enlace jsfiddle .

Más sobre el filtro de matriz aquí .

Nasif Md. Tanjim
fuente
1

¡Puede pasar múltiples argumentos al filtro angular!

Definiendo mi aplicación angular y una variable de nivel de aplicación -

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

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

Y desde HTML enviará datos como: -

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

Aquí estoy enviando un objeto JSON al filtro. También puede enviar cualquier tipo de datos como cadenas o números.

también puede pasar un número dinámico de argumentos para filtrar, en ese caso, debe usar argumentos para obtener esos argumentos.

Para una demostración funcional, vaya aquí: pasando múltiples argumentos al filtro angular

Partha Roy
fuente
0

Simplemente puede usar | filter:yourFunction:arg

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

Y en js

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