1

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
    }]
  }]
});
7
  • @developer033 Because I thought that was what I was supposed to do to get to the most bottom level object. Is it wrong? Commented Jul 3, 2016 at 1:28
  • pls make $scope.search=[]; to $scope.search={}; or $scope.search={'type1': null, 'type2': null}; Commented Jul 3, 2016 at 1:34
  • @JaeeunLee can you make a fiddle for this? Commented Jul 3, 2016 at 1:37
  • Well, in your 3rd. ng-repeat the "item" is still an Array. Commented Jul 3, 2016 at 1:51
  • @developer033 Sorry, JSON was wrong. fixed and added plunker. Commented Jul 3, 2016 at 1:58

1 Answer 1

1

To filter by multiple attributes, in your case, you should add this: filter: { is_gluten_free: search.is_gluten_free, is_vegan: search.is_vegan }.

Also, when you need to use nested ng-repeat, is good to use ng-repeat-start / end directives.

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
        }
      ]
   },
   {  
      "desserts":[  
        {  
          "name":"Whipped Cream",
          "price":25.5,
          "description":"Whipped cream is cream that is whipped by a whisk or mixer until it is light and fluffy. Whipped cream is often sweetened and sometimes flavored with vanilla, and is often called Chantilly cream or crème Chantilly.",
          "image_url":"http://cf.houseofyumm.com/wp-content/uploads/2014/11/Peppermint-Whipped-Cream2.jpg",
          "is_vegan":true,
          "is_gluten_free":true
        }
      ]
   }
];
  
  $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-false-value=''>
        <label for="glueteen">Gluten Free</label>
      </div>
      <div class="filter">
        <input name="vegan" type="checkbox" ng-model='search.is_vegan' data-ng-false-value=''>
        <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" ng-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 ng-src="{{item.image_url}}" alt="{{item.name}} image">
          </div>
          <h3 ng-bind="item.name"></h3>
          <p ng-bind="item.description"></p>
          <p ng-bind="'Vegan: ' + item.is_vegan + ', Gluten free: ' + item.is_gluten_free" class="content-filters"></p>
          <p ng-bind="item.price | currency" class="price"></p>
        </li>
      </ul>
    </section>
  </div>
</body>
</html>

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

2 Comments

Seems like there is an error. If you check "gluten free," only the gluten free item shows. However, if yo uncheck it, the item disappears.
@JaeeunLee, I fixed it.

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.