The Maestro
The Maestro

Reputation: 689

AngularJS multiple filters

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}">

Upvotes: 1

Views: 6830

Answers (2)

VjyV
VjyV

Reputation: 334

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>

Upvotes: 1

Tacocat
Tacocat

Reputation: 1134

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

Upvotes: 8

Related Questions