Jaeeun Lee Jaeeun Lee - 5 months ago 96
Javascript Question

AngularJS Filter By Multiple Keys with Boolean Values

I'm trying to set a filter system with two filters "vegan" and/or "gluten free" for a food menu. Each menu item object has "is_vegan" and "is_gluten free" that are either true or false.

I've tried using checkboxes with ng-models and angular's filter function.

The problem with the current system is that it will display an item that is "is_vegan: true" even when I want to search something that is true for gluten free.

http://plnkr.co/edit/YZftSjR73ID6T1wndoFy?p=preview

HTML:

<body ng-app="bakeryMenuApp">
<div class="wrap" ng-controller="mainCtrl">

<div class="search-filters">
<div class="filter">
<input name="gluteen" type="checkbox" ng-model='search.type1' data-ng-true-value='true' data-ng-false-value='false'>
<label for="glueteen">Gluten Free</label>
</div>
<div class="filter">
<input name="vegan" type="checkbox" ng-model='search.type2' data-ng-true-value='true' data-ng-false-value='false'>
<label for="vegan">Vegan</label>
</div>
</div>

<section class="content-category" ng-repeat="menu in menus">
<div ng-repeat="(key, items) in menu" class="{{key}}">
<h2>{{key}}</h2>
<ul>
<li ng-repeat="item in items | filter:search.type1 | filter:search.type2">
<div class="img-container">
<img src="{{item.image_url}}" alt="{{item.name}} image">
</div>
<h3>{{item.name}}</h3>
<p>{{item.description}}</p>
<p class="content-filters">{{item.is_vegan}}, {{item.is_gluten_free}}</p>
<p class="price"><span>$</span>{{item.price}}</p>
</li>
</ul>
</div>
</section>

</div>
</body>


JS:

var app = angular.module("bakeryMenuApp", []);
app.controller('MainCtrl', function($scope) {
$scope.search=[];
$scope.menus = [{
"brownies": [{
"name": "Baker's Choice Bars Assortment",
"price": "45",
"description": "A beautiful and delicious assortment of Magnolia Bakery’s double fudge brownies, chocolate chunk blondies and magic cookie bars.",
"image_url": "https://pantograph0.goldbely.com/s364/uploads/product_image/image/8346/bakers-choice-bars-assortment.1ddd25a1f59a89a1de2d0583dab50000.jpg",
"is_vegan": true,
"is_gluten_free": false
}]
}, {
"cakes": [{
"name": "Raseberry Lemon Cake",
"price": "50",
"description": "Vanilla crème fraîche cake layered with raspberry Swiss meringue buttercream and lemon curd filling, covered with raspberry buttercream.",
"image_url": "http://www.empirecake.com/_main_site/wp-content/uploads/2014/12/Rasberry_Lemon_01_final_drkr-600.jpg",
"is_vegan": false,
"is_gluten_free": true
}]
}]
});

Answer

To filter by multiple attributes you should add filter: { is_gluten_free: search.is_gluten_free, is_vegan: search.is_vegan }".

Here's is a snippet working:

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

app.controller('mainCtrl', function($scope) {
  $scope.menus = [{
   "brownies": [{
     "name": "Baker's Choice Bars Assortment",
     "price": "45",
     "description": "A beautiful and delicious assortment of Magnolia Bakery’s double fudge brownies, chocolate chunk blondies and magic cookie bars.",
     "image_url": "https://pantograph0.goldbely.com/s364/uploads/product_image/image/8346/bakers-choice-bars-assortment.1ddd25a1f59a89a1de2d0583dab50000.jpg",
     "is_vegan": false,
     "is_gluten_free": true
   }]
  }, {
   "cakes": [{
     "name": "Raseberry Lemon Cake",
     "price": "50",
     "description": "Vanilla crème fraîche cake layered with raspberry Swiss meringue buttercream and lemon curd filling, covered with raspberry buttercream.",
     "image_url": "http://www.empirecake.com/_main_site/wp-content/uploads/2014/12/Rasberry_Lemon_01_final_drkr-600.jpg",
     "is_vegan": false,
     "is_gluten_free": false
    }]
  }];
  
  $scope.search = {};
});
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js">
</script>
</head>

<body ng-controller="mainCtrl">
   <div class="wrap">
  <div class="search-filters">
     <div class="filter">
      <input name="gluteen" type="checkbox" ng-model='search.is_gluten_free' data-ng-true-value='true' data-ng-false-value='false'>
      <label for="glueteen">Gluten Free</label>
      </div>
     <div class="filter">
      <input name="vegan" type="checkbox" ng-model='search.is_vegan' data-ng-true-value='true' data-ng-false-value='false'>
      <label for="vegan">Vegan</label>
      </div>
  </div>

  <section class="content-category" ng-repeat="menu in menus">
    <ul>
      <li ng-repeat-start="(key, items) in menu" class="{{key}}">
        <h2 ng-bind="key"></h2>
      </li>
      <li ng-repeat-end ng-repeat="item in items | filter: { is_gluten_free: search.is_gluten_free, is_vegan: search.is_vegan }">
        <div class="img-container">
          <img src="{{item.image_url}}" alt="{{item.name}} image">
        </div>
        <h3 ng-bind="item.name"></h3>
        <p ng-bind="item.description"></p>
        <p ng-bind="item.is_vegan" class="content-filters">, {{item.is_gluten_free}}</p>
        <p class="price"><span>$</span>{{item.price}}</p>
      </li>
     </ul>
    </div>
  </section>
  </div>
</body>
</html>