1

I want to filter my list's items using multiple filters.

This is how I fill my items list (Using Django):

<script type="text/javascript">
    ngApp.controller('FilterInputCtrl', function ($scope, $rootScope) {
        $scope.items1 = [];
        {% for cross in crosses%}

            $scope.items.push
            ({
                id:{{ cross.id }},
                name: '{{ cross.name }}',
                comments: '{{ cross.comments }}',                  
                aliases: '{{ cross.print_lines_aliases }}',                   
            });

        {% endfor %}
    });

</script>

The one filter code is like this:

<li ng-repeat="cross in items | filter:myFilter">

which filters on all the item's fields (id, name, ... etc).

I want to filter the same way but using multiple filters that filter on all fields too. So the user may remeber segments from the name so he enters many segments from the name and then he maye remeber a segment from the comments and so on.

I found this way:

<li ng-repeat="cross in items | filter:{ name: filter1, lines: filter2, comments: filter3 }">

Which works fine, but each filter now is specific for one criterion. The problem is that I don't know how will the user think when searching; maybe he will search for many segements of the comments!

I am looking for a way to apply many filters and each one filters according to every field without specifying a single field to each one. Something looks like this maybe:

<li ng-repeat="cross in items | filter:{filter1, filter2, filter3}">
3
  • <li ng-repeat="cross in filteredItems = (items | filter:filter1 | filter:filter2 | filter:filter3)">, @The Maestro (Created a new scope variable there called filteredItems, which makes it easy to check if there are any items left after filtering; you may wish to display a message such as "No items found" if !filteredItems.length.) Commented Apr 15, 2016 at 6:59
  • It worked perfectly :D thank you very much! Commented Apr 15, 2016 at 7:04
  • Alright! Glad to have solved your problem! Was not entirely sure that this was what you were asking for. Since it is, I have posted it as an answer, :). Would appreciate if you could accept it, :D, @The Maestro Commented Apr 15, 2016 at 7:07

2 Answers 2

8
<li ng-repeat="cross in filteredItems = (items | filter:filter1 | filter:filter2 | filter:filter3)">

If you notice, I have created a new scope variable there called filteredItems. This makes it easy to check if there are any items left after filtering. You may wish to display a message such as "No items found" if !filteredItems.length.

E.g.

<div ng-hide="filteredItems.length" class="row">
    <div class="col-xs-10 col-sm-11 col-md-11">No items found</div>
</div>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much :D That is what I was looking for.
1

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

app.controller('mainController', function($scope) {
    // Data object
    $scope.servers = [
        {name:'ServerA', runlevel:'PAV', mode:'author', env:'intranet' },
        {name:'Server7', runlevel:'PAV', mode:'publish', env:'intranet'},
        {name:'Server2', runlevel:'PAV', mode:'publish', env:'intranet'},
        {name:'ServerB', runlevel:'PAV', mode:'publish', env:'internet'},
        {name:'ServerC', runlevel:'PAV', mode:'publish', env:'internet'},
        {name:'Server1', runlevel:'UAT', mode:'author', env:'intranet'},
        {name:'Server3', runlevel:'UAT', mode:'publish', env:'intranet'},
        {name:'Server4', runlevel:'UAT', mode:'publish', env:'internet'},
        {name:'ServerD', runlevel:'STA', mode:'author', env:'intranet'}, 
        {name:'ServerE', runlevel:'STA', mode:'publish', env:'intranet'}
    ];
    // Filter defaults
    $scope.Filter = new Object();
    $scope.Filter.runlevel = {'PAV':'PAV',
                            'UAT':'UAT',
                             'ST':'ST'
                        };
    $scope.Filter.mode = {'author':'author',
                            'publish':'publish'
                        };
    $scope.Filter.env = {'intranet':'intranet',
                            'internet':'internet'
                        };
    // Default order
    $scope.OrderFilter = 'runlevel';
});

// Global search filter
app.filter('searchFilter',function($filter) {
        return function(items,searchfilter) {
             var isSearchFilterEmpty = true;
              angular.forEach(searchfilter, function(searchstring) {   
                  if(searchstring !=null && searchstring !=""){
                      isSearchFilterEmpty= false;
                  }
              });
        if(!isSearchFilterEmpty){
                var result = [];  
                angular.forEach(items, function(item) {  
                    var isFound = false;
                     angular.forEach(item, function(term,key) {                         
                         if(term != null &&  !isFound){
                             term = term.toString();
                             term = term.toLowerCase();
                                angular.forEach(searchfilter, function(searchstring) {      
                                    searchstring = searchstring.toLowerCase();
                                    if(searchstring !="" && term.indexOf(searchstring) !=-1 && !isFound){
                                       result.push(item);
                                        isFound = true;
                                    }
                                });
                         }
                            });
                       });
            return result;
        }else{
        return items;
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app">
    <div  ng-controller="mainController">
        <h2>Runlevel</h2>
        <label>PAV</label>
        <input  type="checkbox" ng-model="Filter.runlevel.PAV" ng-true-value="PAV"  ng-false-value="!PAV" />&nbsp;
        <label>UAT</label>
        <input  type="checkbox" ng-model="Filter.runlevel.UAT" ng-true-value="UAT"  ng-false-value="!UAT" />&nbsp;
        <label>ST</label>
        <input  type="checkbox" ng-model="Filter.runlevel.ST" ng-true-value="ST"  ng-false-value="!ST"/>
        <hr />
        <h2>Runmode</h2>
        <label>Author</label>
        <input  type="checkbox" ng-model="Filter.mode.author" ng-true-value="author"  ng-false-value="!author" />&nbsp;
        <label>Publish</label>
        <input  type="checkbox" ng-model="Filter.mode.publish" ng-true-value="publish"  ng-false-value="!publish" />
        <hr />
        <h2>Environment</h2>
        <label>Intranet</label>
        <input  type="checkbox" ng-model="Filter.env.intranet" ng-true-value="intranet"  ng-false-value="!intranet" />&nbsp;
        <label>Internet</label>
        <input  type="checkbox" ng-model="Filter.env.internet" ng-true-value="internet"  ng-false-value="!internet" />
        <hr />
        <h2>Server list</h2>
        <table width="100%" cellpadding="5">
            <tr>
                <th ng-click="OrderFilter='name'">Name</th>
                <th ng-click="OrderFilter='runlevel'">Runlevel</th>
                <th ng-click="OrderFilter='mode'">Runmode</th>
                <th ng-click="OrderFilter='env'">Environment</th>
            </tr>
            <tr ng-repeat="server in servers | searchFilter:Filter.runlevel | searchFilter:Filter.mode | searchFilter:Filter.env | orderBy:OrderFilter">
                <td>{{server.name}}</td>
                <td>{{server.runlevel}}</td>
                <td>{{server.mode}}</td>
                <td>{{server.env}}</td>
            </tr>
        </table>
    </div>
</div>

1 Comment

Thanks :D Actually I found this example but t does what I have explained, it has a specific field for each filter which I am trying to avoid

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.