Chapter 4: Safe $apply
HTML
<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="Ctrl">
<button ng-click="increment()">Increment</button>
{{ val }}
</div>
</div>
JavaScript
angular.module('myApp', [])
.config(function($provide) {
// define decorator for $rootScope service
return $provide.decorator('$rootScope', function($delegate) {
// $delegate acts as the $rootScope instance
$delegate.safeApply = function(func) {
var currentPhase = $delegate.$$phase;
// determine if already in $apply/$digest phase
if (currentPhase === "$apply" ||
currentPhase === "$digest") {
// already inside $apply/$digest phase
// if safeApply() was passed a function, invoke it
if (typeof func === 'function') {
func();
}
}
else {
// not inside $apply/$digest phase, safe to invoke $apply
$delegate.$apply(func);
}
};
return $delegate;
});
})
.controller('Ctrl', function ($scope) {
$scope.val = 0;
// method that may or may not be called from somewhere
// that will not trigger a $digest
$scope.increment = function () {
$scope.val++;
//$scope.safeApply();
};
// application component that modifies the model without
// triggering a $digest
setInterval(function () {
$scope.increment();
$scope.$apply();
}, 1000);
});