6

Say I create an Angular app and write some new filters: Show only odds, and show only lucky numbers.

There's an oddList filter and a luckyList filter:

var app = angular.module('app', []);
app.filter('oddList', function() {
    return function(items) {
        var filtered = [];
        angular.forEach(items, function(item) {
            if (item % 2 !== 0)
                filtered.push(item);
        });
        return filtered;
    };
});
app.filter('luckyList', function() {
    return function(items) {
        var filtered = [];
        angular.forEach(items, function(item) {
            if (item === 2 || item === 7 || item === 11)
                filtered.push(item);
        });
        return filtered;
    };
});

In the view portion, I can chain these filters:

<ul><li ng-repeat="number in numbers | oddList | luckyList">{$number}</li></ul>

When this works, I should see 7 and 11 remaining.

I want to make my filters variable for this ng-repeat. Is there something I can do that's similar to this process?

Say I name the variable filter filter:listFilter so that in our controller, we can dynamically update $scope.listFilter.

<ul><li ng-repeat="number in numbers | filter:listFilter">{$number}</li></ul>

And the controller with pseudo code:

app.controller('main', function($scope, $filter) {
    $scope.numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
    $scope.listFilter = $filter('oddList | luckyList');
});

Any idea how I could chain (variable) filters in the controller? Would like to be able to toggle between just odd, just lucky and/or both.

1

1 Answer 1

11

An approach is to use a function to return the filtered data:

function MainCtrl($scope, $filter) {
    $scope.numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

    $scope.filteredNumbers = function() {
        var result = $scope.numbers;

        if ($scope.oddListEnabled) {
            result = $filter('oddList')(result);  
        }        
        if ($scope.luckyListEnabled) {    
            result = $filter('luckyList')(result);
        }

        return result;
    };
}

And the template:

<ul>
  <li ng-repeat="number in filteredNumbers()">
    {{number}}
  </li>
</ul>

Here is a plunkr: http://plnkr.co/edit/4ectDA?p=preview

Sign up to request clarification or add additional context in comments.

4 Comments

gorgeous! didn't even consider using a function as the ng-repeat data provider. Thanks
But is it possible to do something like <li ng-repeat="product in products | filter:{{selectedFilter}}"> and a <select ng-model="selectedFilter">, so the filter changes automaticaly?
Yes, @ViniciusPires you can also define custom filters: '<li ng-repeat="num in numbers | filteredNumbers:enabledList">' by using ":", you can pass new arguments into the function: ' filter('filteredNumbers', function () { return function filteredNumbers (numbers, enabledList) {}; }); '
Sorry, I think I didn't make myself clear enough... I was asking if it is possible to change the filter at runtime, setting a new value to the filter from a controller or a direct data-bind... By this time I figured out that it's possible to make what I said with just a little change: <li ng-repeat="product in products | filter:selectedFilter">... So it is possible to set the value of $scope.selectedFilter to { name: 'Coke' } or { category: 'Soda'}, depending of what is selected by the user in the combo <select ng-model="selectedFilter">... Just sharing :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.