To illustrate how the functions $ watch (), $ digest (), and $ apply () work, take a look at this example:
<div ng-controller="myController"> {{data.time}} <br/> <button ng-click="updateTime()">update time - ng-click</button> <button id="updateTimeButton" >update time</button> </div> <script> var module = angular.module("myapp", []); var myController1 = module.controller("myController", function($scope) { $scope.data = { time : new Date() }; $scope.updateTime = function() { $scope.data.time = new Date(); } document.getElementById("updateTimeButton") .addEventListener('click', function() { console.log("update time clicked"); $scope.data.time = new Date(); }); }); </script>
In this example, the binding of the variable $ scope.data.time to the interpolation directive, which combines the value of the variable into an HTML page. This binding creates a clock inside the $ scope.data.time variable.
The example also contains two buttons. The first button has an ng-click listener attached to it. When this button is pressed, the $ scope.updateTime () function is called, and after that AngularJS calls $ scope. $ Digest (), so the data bindings are updated.
The second button gets a standard JavaScript event listener attached to it from inside the controller function. When the second button is pressed, the listener function is executed. As you can see, the listener functions for both buttons do almost the same thing, but when the second button listen function is called, the data binding is not updated. This is because $ scope. $ Digest () is not called after the second button event listener is executed. Thus, if you press the second button, the time will be updated in the variable $ scope.data.time, but the new time will never be displayed.
To fix this, we can add $ scope. $ digest () call the last line of the button event listener, for example:
document.getElementById("updateTimeButton") .addEventListener('click', function() { console.log("update time clicked"); $scope.data.time = new Date(); $scope.$digest(); });
Instead of calling $ digest () inside the button's listener function, you could also use the $ apply () function as follows:
document.getElementById("updateTimeButton") .addEventListener('click', function() { $scope.$apply(function() { console.log("update time clicked"); $scope.data.time = new Date(); }); });
Notice how the $ scope function. $ apply () is called from within the button's event listener, and as an update to the $ scope.data.time variable, it is executed inside the function passed as a parameter to the $ apply () function. When the call to the $ apply () function ends, AngularJS calls $ digest () internally, so all data bindings are updated.