1

I am trying to get normalized value of one array associated to different groups.

http://jsfiddle.net/k5Dvj/5/

I don't want to add something new into the original array items, so I am returning new objects for normalized items for each group.

$scope.nomalizedItems = function (groupid) {
    var groupItems = $scope.originalItems.filter(function (item) {
        return item.groupid == groupid
    });

    var values = groupItems.map(function (item) {
        return item.value;
    });
    var maxValue = Math.max.apply(null, values);
    return groupItems.map(function (item) {
        return {
            id: item.id,
            normalizedValue: item.value / maxValue
        };
    });
};

I believe this logic is really simple, however angularjs is always blaming "[$rootScope:infdig] 10 $digest() iterations reached. Aborting!" even if I have added the "track by item.id" in the ng-repeat expression.

Any idea how to solve this issue? Thanks!

bigbearzhu
  • 2,381
  • 6
  • 29
  • 44
  • It's been a while since I worked in Angular, so I can't remember exactly how it works or if it will apply to your situation, but this is how I handled grouping via a filter http://stackoverflow.com/a/15864479/740639 – Walter Stabosz Feb 10 '14 at 22:34
  • @WalterStabosz, Thanks for the link. It is not only grouping, it also needs aggregate on the grouped items to get the max value. And that is the trickiest part since I couldn't use filters to get the max value. – bigbearzhu Feb 11 '14 at 06:34

1 Answers1

2

ngRepeat directive is not happy. Your code creates new objects each time. Digestion loops over and over again...

From what I know, the track by expression is not supposed to make angular match the previous entities with the corresponding new ones after you erased all their internal $$hashKey properties by recreating the entities. This instruction is designed to tell ngRepeat directive how to build this internal $$hashKey to avoid DOM element creation waste.

So .. You may only alter your items instead of creating new ones:

    groupItems.forEach(function (item) {
        item.normalizedValue = item.value / maxValue;
    });
    return groupItems;

And then it works.

Moreover, your filtering is happening at each digest loop. For performance purposes, you may prefer bake this array in specific events/watchers callbacks.

UPDATE

Actually, digestion won't loop over and over again if you bake this list outside of the ngRepeat expression ! I suggest you to have a controller per group using the child scopes created by the ngRepeat directive and bake this list in a watcher callback.

atondelier
  • 2,424
  • 15
  • 11
  • Hmm, did try modify the scope data directly. That did work. Unfortunately I just don't like this way because it's adding new things into the data. But maybe that is the only solution for now? Good explanation for why this error is always showing. I would accept this is my choice of answer! – bigbearzhu Feb 11 '14 at 22:52