Search code examples
javascriptangularjsangularjs-directiveangularjs-scopeangularjs-ng-repeat

ng repeat on a array to filter a key on another object to get the associated value and use watch on that value


Let say i have a object called,

scope.rec = {a: 2, b: 3, name: a,b};

And i split the "name" key like scope.x = scope.rec.name.split(","); then scope.x will become an array.

Now i need to iterate over "scope.x" in the view and get the value associated with the matching property name on scope.rec. I only want to iterate over the valid property names, so I will need to use a filter on scope.x, but it is not working as I would expect.

Once I get the first part working, I will also need to add functionality to multiply the values of the scope.rec properties together - in the example above, it is only 2 numbers (a,b), but it could be more than 2.

Below is the code that I tried.

 scope.x  =
 scope.rec.name.split(",");
scope.myFilter = function(y) {
   if(!scope.rec.hasOwnProperty(y)) return false;
   scope.ys = Number(scope.rec[y]);
    return scope.ys;
        };

html:

<div ng-repeat="y in x | filter:myFilter">
            <label for="{{y}}">{{y}}</label>
            <input type="number" id="{{y}}" value={{ys}}>
    </div>
<div><input id="calc" type="number" ng-model="calc()" disabled></div>

Now the ys in the input is same for both inputs, and the calc() function does not calculate the values correctly.

Appreciate your help in advance.


Solution

  • your filter (at least how you use it in your view) will receive an array with all elements, not just one. So you need to return a complete array

    angular.module('myApp').filter('myFilter', function() {
        return function(arrayOfYs, recFromScope) {
          var filtered = [];
          arrayOfYs.forEach(function(y){
            if(!recFromScope.hasOwnProperty(y)) return;
            // if the value in the object is already a number, it is not necessary to use Number. If it is not the case, add it
            filtered.push(scope.rec[y]);
          });
          return filtered;
        }
    });
    

    and return the filtered data.

    According to your view, you need to use angular filters.

    for you input you should use this

    <input type="number" id="{{y}}" value={{y}}>
    

    although I would remove that id - ids needs to be unique and probably there are values repeated.

    for your calc() function you can use reduce to multiply them

    $scope.calc = function(){
        return $scope.filteredItems.reduce(function(prev, current) {
             return prev * current;
        }, 1);
    };
    

    and to get a reference to $scope.filteredItems use this in your view

    <div ng-repeat="y in (filteredItems = (x | filter:myFilter:rec))">