DivZero
DivZero

Reputation: 2438

Dynamic filter within ng-repeat in AngularJS

For my AngularJS app I have an ng-repeat in an ng-repeat like so:

Html:

<div ng-app="myApp">
    <div ng-controller="myController">
        <h2>working filter</h2>
        <div ng-repeat="category in categories">
            <h3>{{category}}</h3>
            <div ng-repeat="item in items | filter:{price.red: 0} ">{{item.name}}</div>
    </div>

        <h2>broken filter</h2>
        <div ng-repeat="category in categories">
            <h3>{{category}}</h3>
            <!-- price[category] should be red, blue, yellow, depending on the category in the ng-repeat -->
            <!-- price[category] should be bigger then 0 (or not zero, negative values will not occur) -->
            <div ng-repeat="item in items | filter:{price[category]: 0} ">{{item.name}}</div>
        </div>

    </div>
</div>

Javascript:

var myApp = angular.module('myApp', []);

myApp.controller('myController', function ($scope) {

    $scope.categories = ['red', 'blue', 'yellow'];
    $scope.items = [
        {name: 'one', price:{red: 0, blue: 1, yellow: 3} },
        {name: 'two', price:{red: 2, blue: 0, yellow: 0}},
    ]    

});

Please see my jsFiddle http://jsfiddle.net/hm8qD/

So I ran into two problems:

  1. The flter does not accept [] brackets so I cannot make the filter dynamic, based on the category
  2. The filter needs to return items that have a price[category] greater then zero.

For the greater then zero I could just make a custom filter. However as far as I know filters don't accept parameters so I have no way of getting the category (red, blue or yellow) to it.

Please note this is an simplified version of my actual code and this context might not make the best of sense. I hope I was clear in explaining what I need the filter to do, since I'm new to AngularJS.

Upvotes: 5

Views: 16057

Answers (2)

Fraction
Fraction

Reputation: 463

I found a different and quite neat solution for sending parameters to the filter (written in es6):

$scope.myFilter = (category) => {
  return (item) => {
    if(category === 'fish' && item.type === 'salmon'){
       return true
    }
    return false
  }
}

the markup would be:

<div ng-repeat="item in items | 
filter:myFilter(someCategory)>
     {{item.name}}
</div>

So basically you can just scope the "category" into the filter as myFilter returns a function on the format expected by the filter.

Upvotes: 2

DivZero
DivZero

Reputation: 2438

Apparently it is actually possible to pass arguments to your filter, but you have to make a custom filter instead of using "filter: expression". What I did was create a custom filter which takes the items and category as arguments and returns the array with filtered items.

myApp.filter('myFilter', function () {
    return function (items, category) {
        var newItems = [];
        for (var i = 0; i < items.length; i++) {
            if (items[i].price[category] > 0) {
                newItems.push(items[i]);
            }
        };

        return newItems;
    }
});

See the updated Fiddle here: http://jsfiddle.net/hm8qD/3/  

Upvotes: 3

Related Questions