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);
}
}
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.
$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.
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.
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.
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).
$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 love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With