Skip to content Skip to sidebar Skip to footer

"$apply Already In Progress" When Opening Confirm Dialog Box With Firefox

I am (sometimes) getting a weird $apply already in progress error when opening a confirm dialog box in the following and innocent looking situation : The error message is : $roo

Solution 1:

After some analysis, it seems to be a surprising interaction between the $interval and modal dialog in Firefox.

What is the problem ?

The callstack shows something strange : an AngularJS function tick is called within the controller's start function. How is that possible ?

Well, it seems that Firefox does not suspend the timeout/interval functions when displaying a modal dialog box : this allows configured timeout and intervals callback to be called on the top of the currently executing javascript code.

In the above situation, the start function is called with an $apply sequence (initiated by AngularJS when the button was clicked) and when the $interval callback is executed on the top the start function, a second $apply sequence is initiated (by AngularJS) => boom, an $apply already in progress error is raised.

A possible solution

Define a new confirm service (adapted from this and that blog posts) :

// This factory defines an asynchronous wrapper to the native confirm() method. It returns a// promise that will be "resolved" if the user agrees to the confirmation; or// will be "rejected" if the user cancels the confirmation.
mod.factory("confirm", function ($window, $q, $timeout) {

    // Define promise-based confirm() method.functionconfirm(message) {
        var defer = $q.defer();

        $timeout(function () {
            if ($window.confirm(message)) {
                defer.resolve(true);
            }
            else {
                defer.reject(false);
            }
        }, 0, false);

        return defer.promise;
    }

    return confirm;
});

... and use it the following way :

// this function starts some service on the backend$scope.start = function() {
  confirm('Are you sure ?').then(function () {
    $http.post('start.do').then(function (res) {
      $scope.started = true;
    });
  });
};

// this function stops some service on the backend$scope.stop = function() {
  confirm('Are you sure ?').then(function () {
    $http.post('stop.do').then(function (res) {
      $scope.started = false;
    });
  });
};

This solution works because the modal dialog box is opened within an interval's callback execution, and (I believe) interval/timeout execution are serialized by the javascript VM.

Solution 2:

I was having the same problem in Firefox. Using window.confirm rather than just confirm fixed it for me.

Post a Comment for ""$apply Already In Progress" When Opening Confirm Dialog Box With Firefox"