0

I'm wanting to filter on multiple checkboxes but I'm only able to select one at a time. Not sure how to structure this so I can filter on all values.

I've created a fiddle, any help is appreciated.

<input type="checkbox" id="cb" ng-model="word"  ng-true-value="has kitchen" ng-false-value="">

Jimi

1 Answer 1

1

The main issue with not being able to select both checkboxes simultaneously is because they are both bound to the same model property.

As previously stated you had some other declarative issues with the filter, but I think creating a custom filter is probably overkill for your needs anyway.

My approach would be to create an array of options that tracks each selection individually:

  $scope.options = [
  { 
    name: 'has kitchen', 
    selected: false 
  }, { 
    name: 'has bakery', 
    selected: false 
  }];

and iterate over them to build your checkboxes

<label ng-repeat="option in options">
   <input type="checkbox" ng-model="option.selected"/>{{option.name}}
</label>

Then to make things a bit more clear (and avoid some unnecessary nesting), we can simplify the model you're working with to this

  $scope.data = [{
    "name" : "one",
    "services" : ["has bakery", "has dispensary"],
    "address" : "21 regent st chippendale"
  },{
    "name" : "two",
    "services" : ["has bakery", "has dispensary", "has food hall", "has kitchen"],
    "address" : "25 regent st chippendale"
  },{
    "name" : "three",
    "services" : ["has food hall", "has kitchen"],
    "address" : "25 regent st chippendale"
  }];

You can use a simple controller function to provide the filtering

<ul>
  <li ng-repeat="item in data | filter:itemFilter">{{item.name}}</li>
</ul>

The filter function gets called once for each item and returns true if that item has all of the selected options, and false otherwise.

  $scope.itemFilter = function(item) {
    var filters = $scope.options.filter(function(element, idx, array) {
      return element.selected;
    }) || [];

    var matched = true;
    filters.forEach(function(option) {
      matched = matched && item.services.indexOf(option.name) >=0;
    })
    return matched;
  };

Granted this is a simplified version of the matching logic (with the regular exp stuff removed), but it should demonstrate the mechanics and then you can take if from there.

Here's a working example http://plnkr.co/edit/nyBqQAHx8VgbNFICZMou

Edit

Here's another version that should work with your original json model

<ul>
  <li ng-repeat="item in data.list | filter:itemFilter">{{item.name}}</li>
</ul>

and the new filter function (not really elegant, but seems to work for the cases I tried)

  $scope.itemFilter = function(item) {
    var filters = $scope.options.filter(function(element, idx, array) {
      return element.selected;
    }) || [];

    var matched = true;
    filters.forEach(function(option) {
       var matchingService = item.services[0].services.filter(function(element, idx, array) {
         return element.serviceName == option.name;
       }) || [];
       matched = matched && matchingService.length > 0;
    });

    return matched;
  };

Updated example http://plnkr.co/edit/Wlk5wQdXS7OZhSNxhqOA

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

2 Comments

Hi @MPowerKC, thanks for answering the question so concisely. I can't change the JSON i'm afraid, as its part of the overall infrastructure, but you have definitely given me some ideas to try.
@Jimi I see, take a look at the edit above which uses the original json format. Hope this helps :)

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.