2

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);
                    }
                });
            });
1

3 Answers 3

2

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.

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

5 Comments

Thank you @Artyom Pranovich..what if I want to show the data, without checking the check boxes, by default and hide the items based on selection.
@SateeshKumarAlli, am I right that you'd like the implementation like that plnkr.co/edit/5OUyv6XT3vTdan7Amqkg?p=preview? It displays all data the first time when you load the page and then filter the data based on checkbox selections.
exactly. Thank you. It would be nice if the data is shown when check boxes are un-checked.
@SateeshKumarAlli, here is what did you ask for plnkr.co/edit/EnbY8w2fg6uBPQFGUuyk?p=preview
This helps me. Thank you very much. @ArtyomPranovich
1

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

4 Comments

Thank you @KrishCdbry. This example filters interests but I would like to filter users based on interests.
Yes done ! I have edited the answer please have a look at it. It will work
Your code is working fine but it's not giving desired output. Suppose if I select reading and sports it should show both John and Rosaline but it's showing only one person. I'll go with @Artyom Pranovich's solution
I though all selected interests should be there, But if any one of them then I updated. It is just a line change. you can visit the plunker now
0

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;
}

Comments

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.