AngularJS offers an excellent feature known as two-way data binding. Data binding means when the value is been changed in the view, then the scope model will automatically gets updated and in the similar way of the scope model changes then the view will be updated itself by the new value. Now how this is been done ??
For this, angularJS will set up a watcher on the scope model, it will be updated on the view and same if the view changes it will be updated in the scope model.
Syntax :
$scope.$watch('updateValue', function(newvalue, oldvalue) {
//here it will update the DOM element with the new value
});
Here, the second argument which is been passed to the $watch() is known as the listener function and it is called whenever the value of updateValue changes. It is easy for us to remember that when the value changes the listener will be called, with updating the expression in HTML. Now we get a doubt that how does angular will know when the updateValue is been changed so that it can call it's respective listener. So, to solve this $digest cycle comes into the picture.
The $digest cycle starts with a call of $scope.$digest(). For Example the scope function can be changed in the handler function through the ng-click directive or it can be any other directive . In this case when the scope gets changed the angular will call the $digest cycle by calling the $digest() and it will then fire the each watch. These watchers will check if the current value of the scope model is different from the old value. If yes, then the respected listener function will be executed. As a result, if there are any expression in the view they will be updated. In addition to this event, there are several other directives/services which will let you change models and automatically triggers a $digest cycle.
Angular will never call the $digest() method directly. Instead of this, it calls $scope.$apply() which will in turn call the $rootScope.$digest(). So, the digest cycle starts with the $rootScope and it will visit all the child scopes by calling the watchers.
For Example :
when we attach a ng-click directive to a button and a pass a function name to it. Now, when the button is clicked, the angular will just wrap the function call in the $scope.$apply() and next the digest() comes in to verify whether the changes are been reflected in the view or not.
$scope.$apply() will automatically call the $rootScope.$digest(). The $apply() is of two types.
The first is function will be taken as argument, evaluates it and triggers a $digest cycle.
The second doesn't take any arguments, it just starts a $digest cycle when it is been called.
For all built-in directives angular will wrap the code in $apply() and starts $digest() cycle. There would be a chance for us to call the $apply() manually i.e. if the model is been changed outside of the angular context then we need to inform angular the changes by calling the $apply() manually. It is like we are informing angular that the you are changing some models and the watchers need to be fired so that your changes can be done properly.
For Example :
If we use setTimeout() function to update a scope model. Angularjs doesn't know what has been changed. so for this we need to call $apply() to make sure that the changes take effect.
angular.module('myApp',[]).controller('MessageController', function($scope) {
$scope.getMsg = function() {
setTimeout(function() {
$scope.msg = 'fetched message after 3 seconds';
console.log($scope.msg);
}, 2000);
}
$scope.getMsg();
});
Here, we need to see that the model needs to get updated after a two second interval but doesn't get updated because we didn't apply the $apply() function. So, we need to add $apply() function in the above code as shown :
$scope.getMsg = function() {
setTimeout (function() {
$scope.$apply(function() {
$scope.msg = 'fetched message after 3 seconds';
console.log($scope.msg);
}
}, 2000);
}
$scope.getMsg();
});
Now the view gets updated after two seconds and the only change in the code is $scope.$apply() which will automatically trigger $rootScope.$digest so the watchers will be fired and the data will be updated.
Always we need to use version $apply() that accepts a function argument because when a function is passed to the $apply() it will wrap the code in the code in try...catch block and if any exception occur then it will be passed to the $exceptionHandler service.
No comments:
Post a Comment