Sateesh Kumar Alli
Sateesh Kumar Alli

Reputation: 288

Angular filter with list of items in an array

I have an array of objects with user and interests. I would like to filter the list based on interests. An user can have multiple interests and when selected interests check boxes the list should filter out based on those interests. I've used a basic filter on ng-repeat but it's not working.

If I select "sports" then "John" and "Rosaline" should be shown. If I select "movies" and "reading" then all 3 users should be shown. Below is my code.

Plunker: https://plnkr.co/edit/A0ojO3MH8rDhFJVXlEAs?p=preview

View:

<div ng-app="myApp" ng-controller="myController" style="padding:20px">
<input type="checkbox" ng-model="selection.reading" ng-true-value="'reading'" ng-false-value="''">reading
<input type="checkbox" ng-model="selection.sports" ng-true-value="'sports'" ng-false-value="''">sports
<input type="checkbox" ng-model="selection.movies" ng-true-value="'movies'" ng-false-value="''">movies
<br><br>
Selected Values: {{selectedValues}}
<hr>
    <div ng-repeat="d in data | filter: selectedValues">
      <h4>
      Name: {{d.user}}
      </h4>

        <h4>
      Interests: {{d.interests}}
      </h4>

      <hr>

</div>

Controller:

$scope.selection = {};
    $scope.data = [
        {
            user: "John",
            interests: ["reading","sports","movies"]
        },
           {
            user: "David",
            interests: ["movies","reading"]
        },
        {
            user: "Rosaline",
            interests: ["sports","movies"]
        }
    ];
    $scope.$watchCollection('selection', function () {
                $scope.selectedValues = [];
                angular.forEach($scope.selection, function (value, key) {
                    if (value) {
                        $scope.selectedValues.push(value);
                    }
                });
            });

Upvotes: 2

Views: 621

Answers (3)

KrishCdbry
KrishCdbry

Reputation: 1059

Modify your html a bit in ng-repeat

<div ng-repeat="d in data" ng-hide="selectedValues.length > 0 && !filteredData(d.interests)">
  <h4>
    Name: {{d.user}}
  </h4>

  <h4>
     Interests: {{d.interests}}
 </h4>

  <hr>

</div>

And add this function in script.js

             $scope.filteredData = function (data) {
             var found = false;
                 for (var i = 0; i < $scope.selectedValues.length; i++) {
                    if (data.indexOf($scope.selectedValues[i]) !== -1) { found = true; break; }
                 }   
              return found;
         };

Live example : https://plnkr.co/edit/y8tqNiIU6p3x8d9zcdzL?p=preview

This will work ! Thanks

Upvotes: 1

Artyom Pranovich
Artyom Pranovich

Reputation: 6962

Here is one of many ways to filter objects in such examples.

I suggest getting rid of using $watch in this situation and implement checkboxes functionality via simple ngChange directive. Example below.

<input type="checkbox" ng-model="selection.reading" ng-change="selectInterest('reading')">reading
<input type="checkbox" ng-model="selection.sports" ng-change="selectInterest('sports')">sports
<input type="checkbox" ng-model="selection.movies" ng-change="selectInterest('movies')">movies

$scope.selectInterest = function(interest){
  $scope.selection[interest] = !!$scope.selection[interest];
};

For filtering data I recommend using $filter or (just to simplify example) implement this filter like a controller function.

$scope.filterUsers = function(user){
  return Object.keys($scope.selection).some(function (item) {
    return user.interests.indexOf(item) >= 0 && $scope.selection[item];
  });
};

You can look at and play with the whole code of my example at the link above.

Upvotes: 2

Andurit
Andurit

Reputation: 5762

Your can keep your filters in some array e.g. filterInterests and then your HTML could looks like:

<div ng-repeat="d in data">
  <div  ng-show="hasInterest(d.interests, filterInterests)">
  // Your code here
  </div>
</div>    

And your function will looks like:

function hasInterest(data, interests){
  var result = false;
  // Iterate over interests from filter and check them all in provided data
  for(var=i, i<interests.length, i++){
   if(data.indexOf(i) != -1) result = true       
   else result = false;
  }
  return result;
}

Upvotes: 0

Related Questions