Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I would like to filter the results.

There is a list of wines, my wish is when no checkbox is checked, the entire list of wine is displayed.

  • when only 1 checkbox is checked is displayed the related category
  • when more than one checkbox are checked the related categories are displayed

I'm a newbie to AngularJS, I tried with ng-model wihout success, here is the code without ng-model associated to the function:

<html ng-app="exampleApp">
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.10/angular.min.js"></script>

    <script>
        angular.module("exampleApp", [])
                .controller("defaultCtrl", function ($scope) {
                    $scope.wines = [
                        { name: "Wine A", category: "red" },
                        { name: "Wine B", category: "red" },
                        { name: "wine C", category: "white" },
                        { name: "Wine D", category: "red" },
                        { name: "Wine E", category: "red" },
                        { name: "wine F", category: "white" },
                        { name: "wine G", category: "champagne"},
                        { name: "wine H", category: "champagne" }

                    ];


                    $scope.selectItems = function (item) {
                        return item.category == "red";
                    };

                    $scope.selectItems = function (item) {
                        return item.category == "white";
                    };

                    $scope.selectItems = function (item) {
                        return item.category == "champagne";
                    };
                });
    </script>
</head>
<body ng-controller="defaultCtrl">

<h4>red: <input type="checkbox"></h4>
<h4>white: <input type="checkbox"></h4>
<h4>champagne: <input type="checkbox"></h4>



            <div ng-repeat="w in wines | filter:selectItems">
                {{w.name}}
                {{w.category}}
            </div>


</body>
</html>

How to use ng-model or ng-change to associate a function to each checkbox button to have a real time filtering model??

share|improve this question
add comment

1 Answer

up vote 1 down vote accepted

There are several implementations possible. Here's one:

  1. Have a $scope.filter = {} object to hold the state of each filter. E.g. {red: true, white: false...}.

  2. Associate each checkbox with the corresponding property using ng-model. E.g.: input type="checkbox" ng-model="filter['red']" />.

  3. Have a function (e.g. $scope.filterByCategory(wine)) that decides if a wine should be displayed or not (based on the $scope.filter object).

  4. Use that function to filter the items based on their category. E.g. <div ng-repeat="w in wines | filter:filterByCategory">


The filterByCategory function could be implemented like this:

$scope.filterByCategory = function (wine) {
    // Display the wine if
    return
            // the wine's category checkbox is checked (`filter[category]` is true)
            $scope.filter[wine.category] ||   // or 

            // no checkbox is checked (all `filter[...]` are false)
            noFilter($scope.filter);
};

where noFilter is a function that checks if there is any filter activated (and returns true if there is none):

function noFilter(filterObj) {
    for (var key in filterObj) {
        if (filterObj[key]) {
            // There is at least one checkbox checked
            return false;
        }
    }

    // No checkbox was found to be checked
    return true;
}

See, also, this short demo.


UPDATE:

I created a modified version, which supports multiple filters (not just filtering by category).
Basically, it dynamically detects the available properties (based on the first wine element), adds controls (groups of check-boxes) for applying filters based on each property and features a custom filter function that:

  1. Filters each wine item, based on every property.
  2. If a property has no filter applied (i.e. no check-box checked), it is ignored.
  3. If a property has check-boxes checked, it is used for filtering out wine items (see above).
  4. There is code for applying multiple filters using AND (i.e. all properties must match) or OR (at least one property muust match).

See, also, this updated demo.

share|improve this answer
    
ExpertSystem, thanks a lot for your answers!! It helps me a lot to understand better AngularJS. I will study your code. Really, very nice solution, thanks a again for sharing yours knowledges!! –  Stéphane Jun 1 at 20:27
    
Hi ExpertSystem, Loading the data with a json file with $http.get, all is works fine, but in the console.log have: TypeError: Cannot read property 'map' of undefined. A last thing, how to put a dynamic counter of the filtered number of wines? Regards!! –  Stéphane Jun 2 at 15:01
1  
@Stéphane: Take a look at the updated fiddle. I added support for originally undefined wines and counting filtered wines. –  ExpertSystem Jun 2 at 18:05
    
Thanks a lot!! I have to pay you a beer!! Really you helped me a lot!! Fantastic help !! –  Stéphane Jun 2 at 18:36
1  
@Stéphane: Take a look at my updated answer (and demo). I am not sure I understood what you meant (but hopefully I did). BTW, yes, I live in Greece :) –  ExpertSystem Jun 13 at 13:15
show 5 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.