How do we use $scope.$apply() in Angular 1.4

$apply() is a core aspect of AngularJS. This is sometimes confusing to understand. This article describes what is $apply() and how do we use $scope.apply() in Angular 1.4.

First things first, we will learn what is $apply(). We know there is an awesome feature called data binding in AngularJS which tells that whenever a model is changed ,the view is updated automatically and vice versa. AnguularJS sets an watcher on the scope model which calls an event listener which updates the view as soon as the model changes. Here some question may arise, how watcher determines when to call the listener? Does it periodically check for changes in the model or something else? The answer is that a $digest cycle starts here.

The $digest cyle starts when $scope.$digest() is called which is fired when we make changes in the model (for example when we use ng-click directive). Each of the watchers are fired when a $digest cycle starts and they check by comparing the current value with last calculated one of the scope model. However $digest is not called directly ,instead $scope.$apply() is called, which in turn calls the $digest automatically that starts a $digest cycle at the $rootScope.

Now by the above description we see $scope.$apply() is called automatically when changes are made in model and as a result a $digest cycle is also started automatically. Then the question when and how to use $apply() manually? The answer is when a model is changed outside the AngularJS’ context. Whenever we need to make changes in a model outside a Angular context, we need to inform Angular to fire its watchers to effect the changes properly i.e. we need to call the $apply() manually.


 

So far we have the idea of $apply(). Let’s see an example. We will now use JavaScript’s setTimeout() function to make changes in scope model.

index.html
[javascript]

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angularjs $apply()</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
<script src="js/script.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="appController">
<button ng-click="display()">Hit me </button>
{{msg}}
</div>
</body>
</html>

[/javascript]

script.js
[javascript]

var app=angular.module(‘myApp’,[]);

app.controller(‘appController’, function($scope) {
$scope.msg="Loading….";
$scope.display = function() {
setTimeout(function() {
$scope.msg = ‘Time elapsed : 5 seconds’;
console.log($scope.msg);
}, 5000);
}
});

[/javascript]

After running the above code we see that value of msg has been changed after 5 seconds in the console but the view remains same (shows ‘Loading…’) as setTimeout() is not from Angular context. It will work if we use Angular’s $timeout. So we need to update our display() function. Let’s do it again with $scope.$apply().

[javascript]

app.controller(‘appController’, function($scope) {
$scope.msg="Loading….";
$scope.display = function() {
setTimeout(function() {
$scope.$apply(function() {
$scope.msg = ‘Time elapsed : 5 seconds’;
console.log($scope.msg);
});
}, 5000);
};
});

[/javascript]

Now running this code we get the desired result as $scope.$apply() triggers starts $digest cycle automatically and watchers are fired which udates the view accordingly.

$scope.$apply() has two vaersions, one takes function as argument and other does not. We could do the above example also with no-argument version as following example

[javascript]

app.controller(‘appController’, function($scope) {
$scope.msg="Loading….";
$scope.display = function() {
setTimeout(function() {
$scope.msg = ‘Time elapsed : 5 seconds’;
console.log($scope.msg);
$scope.$apply(); //no-argument
}, 5000);
}
});

[/javascript]

This works fine but we should always use the $apply() with the function passed as argument as the function called is wrapped up with a try-catch block so that exceptions can be passed and handled through Angular’s $exceptionHandler service.

NOTE : Two way data binding and $scope.$apply() will not be in Angular 2.0 .

Reference : Sitepoint : Understanding Angular’s $apply() and $digest()

If you find this article helpful, you can connect us in Google+ and Twitter.

Enter your email address:

Delivered by FeedBurner


 

Leave a Reply

Your email address will not be published. Required fields are marked *