0
\$\begingroup\$

I'm very new to Angular, and trying to get my head around whether or not I'm doing it the Right Way (tm).

I want to filter a set of results by their properties, where if none of the filters are checked, all the results are displayed, but if one or more filters are checked, all results which match the checked properties are displayed.

I've setup a simple demo with the colours of fruit. The JSFiddle is available at http://jsfiddle.net/mattdwen/u5eBH/2/

The HTML has a series of checkboxs and a repeating list for the set results:

<div ng-app="fruit">
 <div ng-controller="FruitCtrl">
 <input type="checkbox" ng-click="includeColour('Red')"/> Red</br/>
 <input type="checkbox" ng-click="includeColour('Orange')"/> Orange</br/>
 <input type="checkbox" ng-click="includeColour('Yellow')"/> Yellow</br/>
 <ul>
 <li ng-repeat="f in fruit | filter:colourFilter">
 {{f.name}}
 </li>
 </ul>
 Filter dump: {{colourIncludes}}
 </div>
</div>

And the JS adds the checked properties to a scope array, and the filter checks if the fruit colour is in that array:

'use strict'
angular.module('fruit', []);
function FruitCtrl($scope) {
 $scope.fruit = [
 {'name': 'Apple', 'colour': 'Red'},
 {'name': 'Orange', 'colour': 'Orange'},
 {'name': 'Banana', 'colour': 'Yellow'}];
 $scope.colourIncludes = [];
 $scope.includeColour = function(colour) {
 var i = $.inArray(colour, $scope.colourIncludes);
 if (i > -1) {
 $scope.colourIncludes.splice(i, 1);
 } else {
 $scope.colourIncludes.push(colour);
 }
 }
 $scope.colourFilter = function(fruit) {
 if ($scope.colourIncludes.length > 0) {
 if ($.inArray(fruit.colour, $scope.colourIncludes) < 0)
 return;
 }
 return fruit;
 }
}

It doesn't really feel 'Angular' enough to be the correct way to achieve this?

Jonny Sooter
1,38512 silver badges33 bronze badges
asked Mar 17, 2013 at 20:15
\$\endgroup\$
1
  • \$\begingroup\$ I don't have the rep to create an 'Angular' tag unfortunately. \$\endgroup\$ Commented Mar 17, 2013 at 23:28

1 Answer 1

6
\$\begingroup\$

You're attempting to handle the data binding yourself by creating arrays to store objects based on the click event. Angular does the two way binding for you.

Basically, I assign a new property named "included" by assigning it as the model to the input checkbox. Then I use that property on the filter of the fruit array to display only the one's whose colour is selected.

<div ng-app="fruit">
 <div ng-controller="FruitCtrl">
 <div ng-repeat="f in fruit">
 <input type='checkbox' ng-model='f.included'></input>{{f.colour}}
 </div>
 <ul>
 <li ng-repeat="f in fruit | filter:{included:true}">{{f.name}}</li>
 </ul>
</div>
angular.module('fruit', []);
function FruitCtrl($scope) {
 $scope.fruit = [
 {'name': 'Apple', 'colour': 'Red'},
 {'name': 'Orange', 'colour': 'Orange'},
 {'name': 'Banana', 'colour': 'Yellow'}
 ];
}
answered Sep 3, 2013 at 3:41
\$\endgroup\$
2
  • \$\begingroup\$ What if $scope.fruit contains duplicate elements. it will break I think \$\endgroup\$ Commented Sep 29, 2014 at 16:49
  • \$\begingroup\$ Your answer is very good, but it not working as it asked: "if none of the filters are checked, all the results are displayed..." \$\endgroup\$ Commented Aug 6, 2015 at 18:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.