Some of the common directives that use $watch
/ $watchCollection
/ $watchGroup
internally:
- ng-model
- ng-bind / {{ }}
- ng-show & ng-hide
- ng-class
- ng-repeat
- ng-if
- ng-switch
- ng-include
Note that the only one that sets up a two-way binding is ng-model
(scope -> view & view -> scope).
The others set up a one-way binding (scope -> view).
Simply exposing something on for example a controller“s $scope
will not add a watcher.
For example, the following will not result in a watcher being added:
angular.module('myApp', []).controller('Controller', function MyCtrl($scope) {
$scope.value = 1;
});
Together with:
<body ng-app="myApp" ng-controller="Controller">
</body>
But if you replace the HTML with the following one watcher will be added:
<body ng-app="myApp" ng-controller="Controller">
<div>{{value}}</div>
</body>
Some common scenarios when the digest cycle is triggered:
- When
ng-click
is evaluated
- When
ng-model
changes (for example when typing in an input)
- By the
$http
service
- In
$timeout
and $interval
Note that there is one big difference between $apply
and $digest
:
Calling scope.$digest()
will execute the watchers only on that scope and its children.
Calling scope.$apply()
will trigger $digest
on the $rootScope
, which means all the scopes will be traversed and all watchers executed.
$apply
also accepts an expression as an argument. This expression will be evaluated inside a try-catch statement and any exception will be passed on to the $exceptionHandler
service.
$digest
does not accept any arguments.
Usually you only call $digest
instead of $apply
when you are chasing micro optimizations and really know what you are doing.