Chapter 11
AngularJS will keep executing the $digest loop and re-evaluating all the watches
on all scopes till there are no changes reported. Several turns of the $digest loop
are necessary since watch callbacks can have a side effect. Simply put ting a given
callback, executed as a result of a model change, can change the model value that
was already computed and considered as stable.
Let's consider an example of a simple form with two date fields: Start and End. In
such a form the end date should always come after the start date:
<div>
<form>
Start date: <input ng-model="startDate">
End date: <input ng-model="endDate">
</form>
</div>
To enforce in the model that endDate is always after the startDate we could
register watches like:
function oneDayAhead(dateToIncrement) {
return dateToIncrement.setDate(dateToIncrement.getDate() + 1);
};
$scope.$watch('startDate', function (newValue) {
if (newValue <= $scope.starDate) {
$scope.endDate = oneDayAhead($scope.starDate);
}
});
The watch registered in a controller makes two model values interdependent in a
way that changes in one model variable can trigger changes in another. The callback
on model change can have side effects that can potentially change a value that was
already considered "stable".
A good understanding of the dirty-checking algorithm will make you realize that
a given watchExpression is executed at least twice in each and every turn of the
$digest loop. We can quickly confirm this by creating the following mark-up:
<input ng-model='name'>
{{getName()}}
With the getName() expression being a function defined on a scope as follows:
$scope.getName = function() {
console.log('dirty-checking');
return $scope.name;
}