32

I'm getting this error while trying to call

        function MyCtrl1($scope, $location, $rootScope) {
      $scope.$on('$locationChangeStart', function (event, next, current) {
        event.preventDefault();
        var answer = confirm("Are you sure you want to leave this page?");
        if (answer) {
          $location.url($location.url(next).hash());
          $rootScope.$apply();
        }
      });
    }

MyCtrl1.$inject = ['$scope', '$location', '$rootScope'];

Error is

Error: $digest already in progress
iJade
  • 23,144
  • 56
  • 154
  • 243
  • This is a very old post, but still you can refer to this post: http://www.boynux.com/angularjs-apply-explained/ I tried to explain $digest in progress very simple. – Boynux Feb 15 '14 at 14:34

5 Answers5

62

Duplicated: Prevent error $digest already in progress when calling $scope.$apply()

That error you are getting means Angular's dirty checking is already in progress.

Most recent best practices say that we should use $timeout if we want to execute any code in the next digest iteration:

$timeout(function() {
  // the code you want to run in the next digest
});

Previous response: (don't use this approach)

Use a safe apply, like this:

$rootScope.$$phase || $rootScope.$apply();

Why don't you invert the condition?

$scope.$on('$locationChangeStart', function (event, next, current) {                
    if (confirm("Are you sure you want to leave this page?")) {
        event.preventDefault();
    }
});
Community
  • 1
  • 1
bmleite
  • 26,850
  • 4
  • 71
  • 46
  • 3
    updated my whole code...its not showing the error now but its not serving the purpose, to go to next view – iJade Feb 12 '13 at 17:30
  • Does it pass the `if (answer) {` condition? What's the content from `next`? – bmleite Feb 12 '13 at 17:42
  • Do you get any error on the console? Is there any HTTP request going out? – bmleite Feb 12 '13 at 23:20
  • To prevent JS lint errors, use this: if (!$scope.$$phase) { $scope.$apply(); } – Patrick Peters Jul 22 '13 at 08:20
  • 2
    According to the project, you shouldn't use $$phase becaus it's going away in the future and will break your code. http://github.com/angular/angular.js/wiki/Anti-Patterns Instead, just wrap anything you think needs a safe apply inside a $timeout. It will safely apply after the current digest cycle. – betaorbust Feb 19 '14 at 16:44
  • Use `$timeout()`. It has an implied $apply that executes on the next digest cycle. – Benxamin Oct 27 '14 at 16:51
  • try with if(!$scope.$$phase) {} – Ravi Mane Oct 14 '15 at 13:06
13

For others looking to troubleshoot this error, it's worth noting that the docs seem to suggest using the $timeout service to ensure the code will be called in a single $apply block.

$timeout(function() {
  $scope.someData = someData;
});

Also discussed in this question if you look past the accepted answer.

Community
  • 1
  • 1
aw04
  • 10,857
  • 10
  • 56
  • 89
2

Use

$scope.evalAsync(function(){ 
});

instead of

$scope.$apply(function(){
});
josliber
  • 43,891
  • 12
  • 98
  • 133
2

josliber's answer solved a similar $digest problem that I was having. I just used

$scope.$evalAsync(function(){ 
   // code here
});

Good article here https://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm

user2217057
  • 237
  • 3
  • 17
0

Because your $scope.$apply() is inside AngularJs environment.In general I will not suggest you to use $apply(), moreover of $rootScope.$apply() functions make your application run slowly.It runs a new cycle of your whole scope.

Hazarapet Tunanyan
  • 2,809
  • 26
  • 30