Reputation: 61
I am just trying to get some proof of concept working for AngularJS. In the below code, the call to getClass is going to an infinite loop for some reason. The scope variable noOfCalls is set to increment in the function. My expectation was Angular to call this function once for every iteration. Anyone can help?
Plunker link http://plnkr.co/edit/7QvkSEQGTJtExwYm9kgD?p=preview
HTML
<body ng-controller="MainCtrl">
<h1>Total number of calls: {{noOfCalls}}</h1>
<div class="container" ng-repeat="item in arraydata">
<div class="form-group">
<input type="text" class={{getClass(item)}} ng-model=item.name />
</div>
</div>
</body>
Controller
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.arraydata = [];
$scope.arraydata.push({id:1, name: "test1"});
$scope.arraydata.push({id:2, name: "test2"});
$scope.arraydata.push({id:3, name: "test3"});
$scope.noOfCalls=0;
$scope.getClass = function(item)
{
$scope.noOfCalls+=1;
return("form-control");
}
});
Upvotes: 1
Views: 1704
Reputation: 11547
The root cause is as @Chandermani answered that all the expressions will be rerun repeatedly until no change has detected.
For an educational purpose only, if you really want to do something like that, you have to somehow find a way to break the loop. For example.
var childScope = $scope.$new();
childScope.noOfCalls = 0;
$compile($element.find('h1'))(childScope);
$scope.getClass = function(item) {
setTimeout(function () {
childScope.noOfCalls++;
childScope.$digest(); // use $digest here to not trigger digest cycle of parent scopes
}, 0);
return("form-control");
};
Example plunker: http://plnkr.co/edit/d4TB6sh4Sc7MP7FrQyOV?p=preview
The tricks are:
h1
tag with it and store the noOfCalls
flag in this new scope.setTimeout
to defer the increment of noOfCalls
until the digest cycle has finished.childScope.$digest()
to update the h1
in the views but avoid a new digest cycle of parent scopes to be triggered.Upvotes: 0
Reputation: 42669
The number of times an interpolation is evaluated is not controller by you but the framework. Angular calls your function numerous times during a process called digest cycle. This process is used to determine if model has changed for elements that are bound.
In your case you increment noOfCalls
in a function that is define inside the interpolation {{getClass()}}
. This results in changing of noOfCalls variable which is again used in interpolation {{noOfCalls}}
. The digest cycle keeps running or re evaluating your expression till the model is stable or 10 iterations are reached. In the above case model keeps updating again and again with getClass()
evaluation.
Remove the interpolation {{noOfCalls}}
and the iteration would not happen. If you call functions in interpolation or directives that require evaluation of expression, keep the function side affect free.
Read about the digest cycle in developer guide here https://docs.angularjs.org/guide/scope
Upvotes: 2