Rohit Vinay
Rohit Vinay

Reputation: 663

ng-repeat radio filter not working

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

Upvotes: 1

Views: 192

Answers (2)

Pankaj Parkar
Pankaj Parkar

Reputation: 136144

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.

Upvotes: 1

charlietfl
charlietfl

Reputation: 171669

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

Upvotes: 2

Related Questions