Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I guess the title is pretty much clear what I am asking. I have created this fiddle : http://jsfiddle.net/Sourabh_/HB7LU/13142/

In the fiddle I have tried to replicate an async scenario. This is just an example but in an AJAX call if I don't use $scope.$apply() the list does not get updated. I want to know if it is safe to use $scope.$apply() every time I make an AJAX call to update a list or is there some other mechanism I can make use of?

Code I have written to replicate the scenario(same as in fiddle):

HTML

<div ng-controller="MyCtrl">
  <li ng-repeat="item in items">
    {{item.name}}
  </li>
  <button ng-click="change()">Change</button>
</div>

JS

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
  $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"}
                   ];
    setTimeout(function(){callback(testItem)},2000);
  }
}
like image 742
Zee Avatar asked Apr 23 '15 07:04

Zee


People also ask

Why we use scope apply ()?

The $scope. $apply() function takes a function as parameter which is executed, and after that $scope. $digest() is called internally. That makes it easier for you to make sure that all watches are checked, and thus all data bindings refreshed.

What is the difference between Digest () and apply () Why would you ever call Digest () on a scope?

$digest() gets called without any arguments. $apply() takes a function that it will execute before doing any updates. The other difference is what they affect. $digest() will update the current scope and any child scopes.

How use $apply in AngularJS?

In AngularJS, $apply() function is used to evaluate expressions outside of the AngularJS context (browser DOM Events, XHR). Moreover, $apply has $digest under its hood, which is ultimately called whenever $apply() is called to update the data bindings. We will take an example to give a better understanding.

What is the use of scope in angular?

AngularJS Scope The scope is the binding part between the HTML (view) and the JavaScript (controller). The scope is an object with the available properties and methods. The scope is available for both the view and the controller.


1 Answers

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);
  }
}
like image 108
thomaux Avatar answered Oct 27 '22 01:10

thomaux