Passing arguments to angularjs filters
Asked Answered
W

7

100

Is it possible to pass an argument to the filter function so you can filter by any name?

Something like

$scope.weDontLike = function(item, name) {
    console.log(arguments);
    return item.name != name;
};
Wadley answered 1/8, 2012 at 5:56 Comment(0)
H
229

Actually there is another (maybe better solution) where you can use the angular's native 'filter' filter and still pass arguments to your custom filter.

Consider the following code:

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

To make this work you just define your filter as the following:

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

As you can see here, weDontLike actually returns another function which has your parameter in its scope as well as the original item coming from the filter.

It took me 2 days to realise you can do this, haven't seen this solution anywhere yet.

Checkout Reverse polarity of an angular.js filter to see how you can use this for other useful operations with filter.

Hekker answered 23/7, 2013 at 14:57 Comment(3)
In case your filter needs multiple arguments, see How do I call an Angular.js filter with multiple arguments?Crunch
This method also solved a weird issue where inside ng-repeat I couldnt pass my own parameters to my filter. No matter what I did they kept coming back as the index and the overall collection. By doing this return method I was able to pass my parameters and still load the original element, great fix!Tristich
@DennisSmolek I have one doubt I am struck in this point from long time. How are getting access to friend in the filter function $scope.weDontLike. In my case when I try I get the error message saying that 'angular.js:12520 ReferenceError: friend is not defined'Leptorrhine
S
76

From what I understand you can't pass an arguments to a filter function (when using the 'filter' filter). What you would have to do is to write a custom filter, sth like this:

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

Here is the working jsFiddle: http://jsfiddle.net/pkozlowski_opensource/myr4a/1/

The other simple alternative, without writing custom filters is to store a name to filter out in a scope and then write:

$scope.weDontLike = function(item) {
  return item.name != $scope.name;
};
Sweatbox answered 1/8, 2012 at 6:20 Comment(4)
Thats prefect thanks! Storing the name in the scope won't work so well as I have three lists from the same data on the same page im filtering with different states (or names).Wadley
any to set 'Adam' (referring to your JSFiddle) dynamically? it seems impossible (and I guess that's on purpose) to combine ngModel and a custom filter in Angular...Bloodmobile
Is it possible to reorder the parameters of a filter? For example pass the item to the second parameter of a filter?Grandmamma
It is worth noting that in this example the markup is {{ items | weDontLike:'thenameyoudontlike' }} ... right now you have to go to the fiddle to get that. Also worth noting that you can pass multiple params to your custom filter {{ items | weDontLike:'thename':['I am', 'an array']:'and so on' }} you would just add more arguments to your custom filter to have access to them.Helvellyn
E
62

Actually you can pass a parameter ( http://docs.angularjs.org/api/ng.filter:filter ) and don't need a custom function just for this. If you rewrite your HTML as below it'll work:

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

Eternalize answered 21/9, 2012 at 9:44 Comment(5)
Yes. Side note - if somebody's name is '!Adam', you get him like {name:'!!Adam'}.Rhaetian
You can also pass arrays here too like this filter:['Adam', 'john']Campy
jsfiddle link is broken.Cerate
!Adam is the worst name everBrinkmanship
Not-Not-Adam is obviously worse.Surmount
S
31

You can simply do like this In Template

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

In filter

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";
    }
    });
Scribbler answered 9/11, 2015 at 7:58 Comment(1)
This is the best answer. It works with dynamic objects. This should be the accepted answer.Background
I
2

Extending on pkozlowski.opensource's answer and using javascript array's builtin filter method a prettified solution could be this:

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

Here's the jsfiddle link.

More on Array filter here.

Intend answered 10/9, 2015 at 15:7 Comment(0)
E
1

You can pass multiple arguments to angular filter !

Defining my angular app and and an app level variable -

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

Your Filter will be like :-

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

And from HTML you will send data like :-

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

Here I am sending a JSON object to the filter. You can also send any kind of data like string or number.

also you can pass dynamic number of arguments to filter , in that case you have to use arguments to get those arguments.

For a working demo go here - passing multiple arguments to angular filter

Eventual answered 25/5, 2017 at 7:24 Comment(0)
R
0

You can simply use | filter:yourFunction:arg

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

And in js

$scope.weDontLike = function(group) {
//here your condition/criteria
return !!group 
}
Rowen answered 2/7, 2020 at 13:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.