Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter by an array in AngularJs ng-repeat?

I am using ng-repeat to display my data. That is working fine.

One of the data fields in my ng-repeat result set is an array of items. Example: {x:1, y:[2,3,4]} I would like to filter by data by data in the array. I can easily filter by the non array data, but I am having trouble when I try to filer by looking inisde in the array.

Here is my markup ng-repeat = "con in cons | filter: usrSingle.username in con.conPlayerList"

(edited markup to match my example better ng-repeat = "con in cons | filter: '3' in con.y" )

usrSingle is a scope in this controller I can access. I don't get any errors and I can't seem to find examples of this.

More code was requested and here it is below. I forgot to mention this is a MEAN app. I have MongoDB serving the data. I use a REST API for my data calls.

(EDIT) code from the angular module:

// call to the api for data
app.factory('usrService', function ($resource) {
return $resource('/api/users', {});
});
// factory to hold user data between controllers
app.factory('usrTracker', function () {
var vUsrProfile = {
    usrSingle: 'usrSingle'
};
return {
    getProperty: function () {
        return vUsrProfile;
    },
    setProperty: function (value) {
        vUsrProfile = value;
    }
};
});
// angular controller
app.controller('usrPageController', function ($scope, usrTracker, conService, postService) {

var usrSingle = usrTracker.getProperty();
$scope.usrSingle = usrSingle;
$scope.cons = conService.query();
$scope.posts = postService.query();
});

(FINAL EDIT) The answer marked for this is a good solution. But I went another direction. I used the mongoDB $unwind aggregation to explode my data, like below.

code from API file:

// get
.get(function (req, res) {
// unwind on the conPlayerList array field
Con.aggregate([{ $unwind: "$conPlayerList" }], function (err, cons) {
return res.json(cons);
});
})

Then I filtered on the user I was looking for. Changing the HTML Angular markup to this

ng-repeat="con in cons | filter:{conPlayerList:usrSingle.username}"

to match my example better, by removing my specific code, it would be:

ng-repeat="con in cons | filter: {y:'3'} "

like image 443
Trewaters Avatar asked Sep 26 '22 08:09

Trewaters


1 Answers

You can use Angular's built in filter logic on the array, BUT bear in mind this is not an exact match and will match against an array entry of 300 if usrSingle is set to 3, see example in Fiddle.

<div ng-repeat = "con in cons | filter:{y:usrSingle} ">...</div> 

To match exactly against array elements you can use filter: and a predicate function on the controller i.e.

Controller (Fiddle):

app.controller('usrPageController', function ($scope) {
  $scope.filterFn = filterFn;
  $scope.usrSingle = 3;
  $scope.cons = [
      {x:0, y:[1,2,3]},
      {x:1, y:[2,3,4]},
      {x:2, y:[3,4,5]},
      {x:3, y:[4,5,6]},
      {x:4, y:[5,6,7]}
  ];

  function filterFn(con){
    return con.y.indexOf($scope.usrSingle) > -1;
  }
});

View:

<div ng-repeat = "con in cons | filter:filterFn">...</div>

Alternatively you can create a custom filter which can be reused elsewhere in your app and pass usrSingle in as a parameter:

Filter (Fiddle):

app.filter('customFilter', function() {
  return function(input, value) {
    var result = [];
    input.forEach(function(item){
        if(item.y.indexOf(value) > -1){
            result.push(item);
        }
    });
    return result;
  };
});

View:

<div ng-repeat = "con in cons | customFilter:usrSingle">...</div>
like image 188
sheilak Avatar answered Sep 28 '22 23:09

sheilak