Home > Back-end >  Angularjs - NG-repeat with filter to an array not working
Angularjs - NG-repeat with filter to an array not working

Time:08-17

I thought this was going to be the easy part but been going trough google / stack overflow for the past 3 hours with no luck.

I have a straight foward ng-repeat where I want to list everything in my data2 where the ref_id column matches the unique ID of my data1.

data1: [ {id: 1, name: "Bob"}, {id: 2, name: "Diane"}, {id: 3, name: "Ross"}, {id: 4, name: "Jimbo"}, ];

data2: [ {ref_id: 1, Result: "Fries"}, {ref_id: 1, Result: "Burger"}, {ref_id: 7, Result: "Burger"}, {ref_id: 8, Result: "Nothing"}, ];

So this is what I came up with:

<div ng-repeat="result in data2 | filter: { ref_id: data1.id }" > {{ result.Result }} </div>

It seems to be ignoring my filter and just spitting out everything. So i thought maybe it dosent like the array in my filter so I created a custom filter:

<div ng-repeat="result in data2 | filter: Test()"  > {{ result.Result }} </div>

$scope.Test = function(item){

  return angular.forEach($scope.data1, function(value, key) {
    return value.id === item.ref_id;
  }

}

But this simply does not work either, its giving me undefined variables but I think it dosent like the way I use the function. I just want my ng-repeat to display items that have a matching ID to go with my ref_ID column.

Any ideas?

CodePudding user response:

There are two ways to achieve what you are trying to do:

1. Using an init method

Creating a list with the required entries in init method of the controller (better to use $onInit), and then using that list in ng-repeat

// inside the controller for your app
  $scope.data1 = [ {id: 1, name: "Bob"}, {id: 2, name: "Diane"}, {id: 3, name: "Ross"}, {id: 4, name: "Jimbo"}];

  $scope.data2 = [ {ref_id: 1, Result: "Fries"}, {ref_id: 1, Result: "Burger"}, {ref_id: 7, Result: "Burger"}, {ref_id: 8, Result: "Nothing"}];

  var init = function () {
    var idList = $scope.data1.map(function (item) {
      return item.id;    
    });
    $scope.filteredList = $scope.data2.filter(function (item) {
      return idList.includes(item.ref_id);
    });
  }
  init();
// end of controller

And in view:

<div ng-repeat="result in filteredList" > {{ result.Result }} </div>

2. Making a custom filter

angular.module('yourModuleName', []).filter('test', function() {
    return function(input, include, prop1, prop2) {
        if (!angular.isArray(input))
            return input;

        if (!angular.isArray(include))
            include = [];

        if (prop2) {
            // extracting 'id' from data1
            include = include.map(function byProp(item) {
                return item[prop2];
            });
        }
        return input.filter(function (item) {
          // checking if ref_id of current item is present in include, which is a list of ids from data1
          return include.includes(item[prop1])
        });
    };
});
  • input is list used in ng-repeat
  • include, prop1 and prop2 correspond to the parameters used while calling the filter

Using the filter in view:

  <div ng-repeat="result in data2 | test:data1:'ref_id':'id'" > {{ result.Result }} </div>
  • data2 corresponds to input in filter definition
  • include corresponds to data1 sent it through the filter
  • 'ref_id' (string) corresponds to prop1
  • 'id' (string) corresponds to prop2

I picked the accepted answer here and modified it to fit this use case. Hope this helps.

Here's a plnkr including code for both of the above cases: https://plnkr.co/edit/GdvVZIhDbFTaVQPY

Reference for understanding use of multiple filter arguments: How do I call an Angular.js filter with multiple arguments?

  • Related