1

I am using angularJS to filter my data, the filter options are radio buttons fetched from a JSON API, but it does not work though using the usual route. my plunk

HTML

<div class="category">
  <div ng-repeat="category in categories">
    <input type="radio" name="typefilter" id="{{category.title}}" ng-model="typefilter" value='{{category.title}}'>
    <label for="{{category.title}}">{{category.title}}</label>
  </div>
</div>
<div class="food" ng-repeat="food in foods | filter:typefilter">
  <h4>{{food.name}}</h4>
  <p ng-repeat="food in food.type">{{food}}</p>
</div>

Controller

app.factory('Categories', ['$resource',
function ($resource) {
    return $resource('https://safe-depths-4702.herokuapp.com/api/categories/:categoryId', {
      categoryId: '@_id'
    }, {
      update: {
        method: 'PUT'
      }
    });
  }
]).factory('Foods', ['$resource',
  function ($resource) {
    return $resource('https://safe-depths-4702.herokuapp.com/api/foods/:foodId', {
      foodId: '@_id'
    }, {
      update: {
        method: 'PUT'
      }
    });
  }
]).controller('MainCtrl', function($scope,Categories,Foods) {
  $scope.categories = Categories.query();
  $scope.foods = Foods.query();
});

my plunk

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
Rohit Vinay
  • 665
  • 7
  • 38

2 Answers2

2

Whole problem boils down to you are breaking the all important rule of always always always use an object in ng-model

ng-repeat creates a child scope and the typefilter is a primitive only being set in each child scope. The parent scope can't see that primitive

In controller set an object:

 $scope.filter={}

In view use filter.typefilter

<div class="category">
      <div ng-repeat="category in categories">
        <input type="radio" name="typefilter" id="{{category.title}}" ng-model="filter.typefilter" value='{{category.title}}'>
        <label for="{{category.title}}">{{category.title}}</label>
      </div>
    </div>
    <div class="food" ng-repeat="food in foods | filter:filter.typefilter">
      <h4>{{food.name}}</h4>
      <p ng-repeat="food in food.type">{{food}}</p>
    </div>

DEMO

charlietfl
  • 170,828
  • 13
  • 121
  • 150
1

When ng-repeat does render a template, it create a child scope which does prototypically inherited from parent case. And Prototypal Inheritance work on reference type of variable's, not on primitive type variable. In your case you are using primitive type variable, so it didn't get followed in your case.

Here in this case typefilter is scope present inside ng-repeat, so then typefilter is available inside the ng-repeat scope only. You can not get its value outside ng-repeat div. So in that case you need to explicitly point out to the parent scope using $parent. before ng-repeat's primitive type variable.

ng-model="$parent.typefilter"

Working Plunkr

But this isn't a good approach to follow, as it gets tightly couple with parent controller scope(Would not work, if you are using Ionic, as it does create child scope on each ion-content)

Rather you should follow, either one of below approach.

  1. Dot rule while defining model(already covered in @charlietfl answer)
  2. controllerAs approach

In this answer, you could find the other way to solve this issue.

Community
  • 1
  • 1
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • thank you, your solution works on plunker, but did not work on my ionic application. i could use this for browser based applications. thank you – Rohit Vinay Feb 20 '16 at 19:29
  • @RohitKumarVinay yes.. for `ionic` it wouldn't work, because for each `ion-content` it creates a child scope. So i'd suggest follow `charlietfl` way.. thats why I said in my answer that.. its not correct approach to go for it.. Its kind of explanation, do refer mine reference answer. in that I covered whole points – Pankaj Parkar Feb 20 '16 at 19:32