When is it safe to use $scope.$apply()?

The $apply, should be used when the code is not executed in a angular digest loop. In normal circumstances we will not need to use it, but we might have to use it if we have a code that is called from a jQuery event handler or from methods like setTimeout(). Even if you have a function that is called from another angular function like a watch or angular event handlers you need not use $apply() as those scripts are executed in the digest cycle.

One safe way is to check the $scope.$$phase param before calling $scope.$apply() like

if($scope.$$phase){
    $scope.$apply();
}

In your case but you can use $timeout as suggested in the another answer

  • What is $$phase in AngularJS?
  • Why is using if(!$scope.$$phase) $scope.$apply() an anti-pattern?

Edit It was not clear the OP was trying to mock a backend call. Even so, using the $timeout service is a great way to avoid the need of calling $scope.$apply manually and is a more generally applicable solution than using a Promise (in cases where you're i.e. not calling $http it doesn't always make sense to force your changes into the next cycle by wrapping them with a Promise).


Update your code to use the $timeout service and it should work without having to call $apply.

$timeout is a wrapper around the native setTimeout with an important difference: $timeout will delay the execution at least until the next $digest cycle runs.

So passing in no delay will still delay the execution up until the next cycle. Passing in 2000 will delay the execution up to the next cycle after 2000ms.

Hence, this is an easy trick to make sure your changes are picked up by Angular without ever having to call $apply manually (which is considered unsafe in any case)

function MyCtrl($scope, $timeout) {
  $scope.items = [{name : "abc"},{name : "xyz"},{name : "cde"}];

  $scope.change = function(){
    test(function(testItem){
      $scope.items = testItem;
      //$scope.$apply();
    })
  }
  function test(callback){
    var testItem = [
                    {name : "mno"},
                    {name : "pqr"},
                    {name :   "ste"}
                   ];
    $timeout(function(){callback(testItem)},2000);
  }
}

If you want to immidate an API-Rest-Call, use the returned promise in your Controller instead setting the scope inside the Rest-Call.

$http.get('uri')
  .success(function(data) {
    $scope.items = data
});

Avoid using $apply(). From the Angular GitHub Repo:

$scope.$apply() should occur as close to the async event binding as possible.

Do NOT randomly sprinkle it throughout your code. If you are doing if (!$scope.$$phase) $scope.$apply() it's because you are not high enough in the call stack.

To your question:

  • If you find yourself in a situation where you need $apply(), rethink your structure.
  • Just for safety reason: Never use $apply()

You need to use $apply every time you use something that is not "angular way", like Anzeo told about $timeout.
For example if you use jQuery's http instead of angular's $http, you will have to add $scope.$apply.