From a recent discussion with the Angular guys on this very topic: For future-proofing reasons, you should not use $$phase
When pressed for the "right" way to do it, the answer is currently
$timeout(function() {
// anything you want can go here and will safely be run on the next digest.
})
I recently ran into this when writing angular services to wrap the facebook, google, and twitter APIs which, to varying degrees, have callbacks handed in.
Here's an example from within a service. (For the sake of brevity, the rest of the service -- that set up variables, injected $timeout etc. -- has been left off.)
window.gapi.client.load('oauth2', 'v2', function() {
var request = window.gapi.client.oauth2.userinfo.get();
request.execute(function(response) {
// This happens outside of angular land, so wrap it in a timeout
// with an implied apply and blammo, we're in action.
$timeout(function() {
if(typeof(response['error']) !== 'undefined'){
// If the google api sent us an error, reject the promise.
deferred.reject(response);
}else{
// Resolve the promise with the whole response if ok.
deferred.resolve(response);
}
});
});
});
Note that the delay argument for $timeout is optional and will default to 0 if left unset ($timeout calls $browser.defer which defaults to 0 if delay isn't set)
A little non-intuitive, but that's the answer from the guys writing Angular, so it's good enough for me!
Please check this jsFiddle. (The code is basically the same you posted but I use an element instead of the window to bind the scroll events).
As far as I can see, there is no problem with the code you posted. The error you mentioned normally occurs when you create a loop of changes over a property. For example, like when you watch for changes on a certain property and then change the value of that property on the listener:
$scope.$watch('users', function(value) {
$scope.users = [];
});
This will result on an error message:
Uncaught Error: 10 $digest() iterations reached. Aborting!
Watchers
fired in the last 5 iterations: ...
Make sure that your code doesn't have this kind of situations.
update:
This is your problem:
<div ng-init="user.score=user.id+1">
You shouldn't change objects/models during the render or otherwise, it will force a new render (and consequently a loop, which causes the 'Error: 10 $digest() iterations reached. Aborting!').
If you want to update the model, do it on the Controller or on a Directive, never on the view. angularjs documentation recommends not to use the ng-init
exactly to avoid these kinds of situations:
Use ngInit directive in templates (for toy/example apps only, not
recommended for real applications)
Here's a jsFiddle with a working example.
Best Solution
So I finally solved the issue. What I ended up doing was adding a library called Recursion Helper to my project, and injected it as a dependency.
Here is a link to the original post. Thanks!