Danny Soul
Danny Soul

Reputation: 73

Angular $scope won't update in bootbox callback

This is my first question on SO.

When I splice an element of an array on the scope, that change is not reflected, when done in a callback of bootbox.js.

Works:

$scope.deleteA = function() {
    if (confirm("Really delete Item 3?")) {
      $scope.itemsA.splice(2, 1);
    }
}

Does not work:

$scope.deleteB = function() {
    bootbox.confirm("Really delete Item 3?", function(answer) {
      if (answer === true) {
        $scope.itemsB.splice(2, 1);
      }
    });
}

I'm mainly interested in understanding the why. This is much more important to me than having a fancy workaround.

I created a Plunker to show the effect

Upvotes: 7

Views: 1192

Answers (2)

Juned Lanja
Juned Lanja

Reputation: 1484

Safe method to apply scope change would be using $timeout service.

bootbox.confirm("Really delete Item 3?", function(answer) {
  if (answer === true) {
    $timeout($scope.itemsB.splice(2, 1));
  }
});

So you dont need to worry about $digest phase and your $apply will be one high call stack take a look at AngularJS Wiki - Anti-Patterns point -2 .

Don't do if (!$scope.$$phase) $scope.$apply(), it means your $scope.$apply() isn't high enough in the call stack.

Upvotes: 0

Grundy
Grundy

Reputation: 13381

Any change happens with angular scope variable from ouside world of angular, doesn't intimate angular digest system to run digest cycle for updating binding.
In bootbox callback angular not know that something change, that's why not update view.
For solving this issue, you need to kick off digest cycle manually by using $apply method, or $timeout service, like this

bootbox.confirm("Really delete Item 3?", function(answer) {
  if (answer === true) {
    $scope.$apply(function(){
        $scope.itemsB.splice(2, 1);
    });
  }
});

Upvotes: 8

Related Questions