user1532669
user1532669

Reputation: 2378

How do I filter results by checkbox?

I'm trying to filter results by star rating, these filters are checkboxes. I can't get this to work. I keep getting the error:

Error: input is undefined

This is my code so far:

$scope.ratings = [
    { name:'One Star', value:1, selected: true}, 
    { name:'Two Stars', value:2, selected: true},
    { name:'Three Stars', value:3, selected: true},
    { name:'Four Stars', value:4, selected: true},
    { name:'Five Stars', value:5, selected: true}
 ]



.filter('ratingsFilter', function(){
    return function(vehicleResults, ratings){
        console.log(ratings)
    }
 })


<label ng-repeat="rating in ratings">
    <input name="rating" type="checkbox" value="{{rating.value}}" ng-model="rating"> star rating {{rating.value}}
</label>

When displaying the filtered results:

<div ng-repeat="vehicle in (filteredResults = (vehicleResults | filter: priceFilter | ratingsFilter:rating )) | startFrom:(currentPage - 1)*10 | limitTo:10 " class="results-container">

Can anyone give me some pointers on how to filter these results?

Thank you in advance.

Upvotes: 0

Views: 534

Answers (2)

cleftheris
cleftheris

Reputation: 4839

I think your problem lies at the ratings repeater and not on your filter.

When you are using ng-model directive it takes care of the value binding, you cannot have both interpolated value attribute and ng-model on an input element.

I believe what you whant to achieve is best done if you remove the ng-model completely and instead use the ng-checked directive like so:

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

app
  .filter('ratingsFilter', function() {
     return function(items, includedRatings) {
        return items.filter(function (value, index, array) {
            return includedRatings.indexOf(value.rating) > -1;
        });
     };
  })
  .controller('MainCtrl', function($scope) {
  $scope.selectedRatings = [1, 2, 3, 4, 5];
  $scope.toggleRating = function (val) {
      var array = $scope.selectedRatings;
      var isChecked = array.indexOf(val);
      if (isChecked > -1) {
          for (var i = array.length; i--;) {
              if (array[i] === val) {
                  array.splice(i, 1);
              }
          }
      }
      else {
          array.push(val);
      }
  };
   $scope.ratings = [
    { name:'One Star', value:1, selected: true}, 
    { name:'Two Stars', value:2, selected: true},
    { name:'Three Stars', value:3, selected: true},
    { name:'Four Stars', value:4, selected: true},
    { name:'Five Stars', value:5, selected: true}
  ];
  $scope.priceFilter = {};
  $scope.vehicleResults = [
    { name:'Porche', rating: 3, price:80000}, 
    { name:'Ferrari', rating: 1, price:150000},
    { name:'Volvo', rating: 2, price:54000},
    { name:'Batmobile', rating: 5, price:10},
  ];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="main" ng-controller="MainCtrl">
    <label ng-repeat="rating in ratings">
    <input name="rating" type="checkbox" 
           value="{{rating.value}}" 
           ng-click="$parent.toggleRating(rating.value)" 
           ng-checked="$parent.selectedRatings.indexOf(rating.value) > -1" /> 
    star rating {{rating.value}}
    </label> 
    <br />
    <label>
      Price:
      <input ng-model="priceFilter['price']" />
    </label>
    <label>
      selected Rating:
      {{ selectedRatings }}
    </label>
    <ul > 
      <li ng-repeat="vehicle in vehicleResults | filter : priceFilter | ratingsFilter: selectedRatings">
        {{vehicle.name}} - {{vehicle.price | currency}} ({{vehicle.rating}} stars)
      </li>
    </ul>
</div>

Upvotes: 1

maurycy
maurycy

Reputation: 8465

I've created plunk but it's playing tricks on me so here you have codepen

http://codepen.io/maurycyg/pen/RNrxQj

JS

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

app.controller('MainCtrl', function($scope) {
  $scope.ratings = [{
    name: 'One Star',
    value: 1,
    selected: true
  }, {
    name: 'Two Stars',
    value: 2,
    selected: true
  }, {
    name: 'Three Stars',
    value: 3,
    selected: true
  }, {
    name: 'Four Stars',
    value: 4,
    selected: true
  }, {
    name: 'Five Stars',
    value: 5,
    selected: true
  }]

  $scope.vehicles = [{
    name: 'One',
    rating: 1
  }, {
    name: 'Two',
    rating: 2
  }, {
    name: 'Three',
    rating: 3
  }, {
    name: 'Four',
    rating: 4
  }, {
    name: 'Five',
    rating: 5
  }, ]






}).filter('ratingsFilter', function() {
  return function(vehicles, ratings) {
    filteredResults = []
    angular.forEach(vehicles, function(vehicle) {
      angular.forEach(ratings, function(rating) {
        if (vehicle.rating === rating.value && rating.selected === true) {
          filteredResults.push(vehicle)
        }
      })
    })
    return filteredResults;
  }
})

Upvotes: 1

Related Questions