If you find yourself triggering the '$apply already in progress' error while developing with Angular.JS (for me I find I hit most often when integrating third party plugins that trigger a lot of DOM events), you can use a 'safeApply' method that checks the current phase before executing your function. I usually just monkey patch this into the $scope object of my topmost controller, and Angular is nice enough to propagate it throughout the rest of my application for me:
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if(phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
And then just replace $apply with safeApply wherever you need it
$scope.safeApply(function() {
alert('Now I'm wrapped for protection!');
});
Angular's apply is able to run without a function as a parameter, so it will propagate all previous changes to the UI.
I purpose this update:
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if(phase == '$apply' || phase == '$digest') {
if(fn)
fn();
} else {
this.$apply(fn);
}
};