Avinash Raj Avinash Raj - 1 month ago 42
AngularJS Question

Error: [$rootScope:infdig] 10 $digest() iterations reached happens in filter

I have tried all the answers regarding this question but I can't find a way to remove this error. I'm damn sure that this filter function is responsible for causing the above mentioned error.

.filter('collect_ingredients', function() {
return function(input) {
if (!angular.isArray(input)) {
return input;
}

var result = {};
angular.forEach(input, function(value){
if (!result[value.code]) {
result[value.code] = {
statement: value.statement,
code: value.code,
ingredients: [value.ingredient]
};
} else {
result[value.code].ingredients.push(value.ingredient);
}
});

return result;
};
})


I tried putting the logic inside a controller function. But it also produces the same error.

ionic.bundle.js:21157 Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [[{"msg":"fn:


Here is the template code responsible for calling the above filter.

<div class="row" ng-repeat="hStatement in foo.bar|collect_ingredients">


Update

I tried creating an function in the controller which accepts foo.bar as input and returns the altered list.

<div class="row" ng-repeat="hStatement in getIngredientsFromFilter(foo.bar)">


controller.js:

$scope.getIngredientsFromFilter = function(input_lst) {
return $filter("collect_ingredients")(input_lst);
}


filter.js:

.filter('collect_ingredients', function() {
return function(input) {
if (!angular.isArray(input)) {
return input;
}

var result_lst = [];
var result_dict = {};
angular.forEach(input, function(value){
var dict = {};
if (!result_dict[value.code]) {
dict = {
statement: value.statement,
code: value.code,
ingredients: [value.ingredient]
};
result_dict[value.code] = dict;
result_lst.push(dict);
} else {
result_dict[value.code].ingredients.push(value.ingredient);
result_lst.push(result_dict[value.code]);
}
});

return result_lst;
};
})


But this also produces the same error..

Answer

The problem isn't exactly with the filter but with the fact that you are binding directly to the results of the filter in your view, and the filter creates new objects within the results every time it is run.

The Angular digest cycle runs through the filter once and then re-evaluates again to check if anything has changed.

Because your filter creates new objects within the results, this is picked up as a change and another digest cycle is triggered even though the data has the same structure. And so on.

So the fix could be to run the filter once within your controller, then bind to the results of that.

e.g.

$scope.result = $filter("collect_ingredients")($scope.foo.bar);

Fiddle

Update

The code in your update has a similar issue because when the function getIngredientsFromFilter is called repeatedly, a result with new objects is returned each time, and the digest cycle re-triggers.

I'd suggest introducing a directive to handle the nested ng-repeat, then dealing with the filter in the directive controller (again to avoid calling the filter multiple times for the same input). See updated Fiddle here.