I want to create divs repeatedly, the items is objects returned by a function. However the following code report errors: 10 $digest() iterations reached. Aborting! jsfiddle is here: http://jsfiddle.net/BraveOstrich/awnqm/
<body ng-app>
<div ng-repeat="entity in getEntities()">
Hello {{entity.id}}!
</div>
</body>
This was reported here and got this response:
You can see this behavior go away if you move the array outside the Main controller:
because now it is returning the same object each time. You may need to re-architect your model to use a property on the scope instead of a function:
Initialise the array outside of the repeat
Based on @przno comment
BTW second solution @Artem Andreev suggests is not working in Angular 1.1.4 and greater, while first one does not solve the problem. So, I'm afraid for now this is the less spiky solution without disadvantages in functionality
Short answer: do you really need such function or you can use property? http://jsfiddle.net/awnqm/1/
Long answer
For simplicity I will describe only your case - ngRepeat for array of objects. Also, I'll omit some details.
AngularJS uses dirty checking for detecting changes. When application is started it runs
$digest
for$rootScope
.$digest
will do depth-first traversal for scope's hierarchy. All scopes have list of watches. Each watch has last value (initiallyinitWatchVal
). For each scope for all watches$digest
runs it, gets current value (watch.get(scope)
) and compares it towatch.last
. If current value is not equal towatch.last
(always for first compare)$digest
setsdirty
totrue
. When all scopes are processed ifdirty == true
$digest
starts another depth-first traversal from$rootScope
.$digest
ends when dirty == false or number of traversals == 10. In the latter case, the error "10 $digest() iterations reached." will be logged.Now about
ngRepeat
. For eachwatch.get
call it stores objects from collection (returning value ofgetEntities
) with additional information in cache (HashQueueMap
byhashKey
). For everywatch.get
callngRepeat
tries to get object by itshashKey
from cache. If it does not exist in cache,ngRepeat
stores it in cache, creates new scope, puts object on it, creates DOM element, etc.Now about
hashKey
. UsuallyhashKey
is unique number generated bynextUid()
. But it can be function.hashKey
is stored in object after generating for future use.Why your example generates error: function
getEntities()
always returns array with new object. This object doesn't havehashKey
and doesn't exist inngRepeat
cache. SongRepeat
on eachwatch.get
generates new scope for it with new watch for{{entity.id}}
. This watch on firstwatch.get
haswatch.last == initWatchVal
. Sowatch.get() != watch.last
. So$digest
starts new traverse. SongRepeat
creates new scope with new watch. So ... after 10 traverses you get error.How you can fix it
getEntities()
call.hashKey
method for them. See this topic for examples.Hope people who know AngularJS internals will correct me if I'm wrong in something.