$watch(watchExpression, listener, [objectEquality]);
Registers a listener callback to be executed whenever the watchExpression changes.
- The
watchExpressionis called on every call to $digest() and should return the value that will be watched. (watchExpressionshould not change its value when executed multiple times with the same input because it may be executed multiple times by $digest(). That is,watchExpressionshould be idempotent. - The
listeneris called only when the value from the currentwatchExpressionand the previous call towatchExpressionare not equal (with the exception of the initial run, see below). Inequality is determined according to reference inequality, strict comparison via the!==Javascript operator, unlessobjectEquality == true(see next point) - When
objectEquality == true, inequality of thewatchExpressionis determined according to theangular.equalsfunction. To save the value of the object for later comparison, theangular.copyfunction is used. This therefore means that watching complex objects will have adverse memory and performance implications. - The watch
listenermay change the model, which may trigger otherlisteners to fire. This is achieved by rerunning the watchers until no changes are detected. The rerun iteration limit is 10 to prevent an infinite loop deadlock.
If you want to be notified whenever $digest is called, you can register a watchExpression function with no listener. (Be prepared for multiple calls to your watchExpression because it will execute multiple times in a single $digest cycle if a change is detected.)
After a watcher is registered with the scope, the listener fn is called asynchronously (via $evalAsync) to initialize the watcher. In rare cases, this is undesirable because the listener is called when the result of watchExpression didn't change. To detect this scenario within the listener fn, you can compare the newVal and oldVal. If these two values are identical (===) then the listener was called due to initialization.
// let's assume that scope was dependency injected as the $rootScope
var scope = $rootScope;
scope.name = 'misko';
scope.counter = 0;
expect(scope.counter).toEqual(0);
scope.$watch('name', function(newValue, oldValue) {
scope.counter = scope.counter + 1;
});
expect(scope.counter).toEqual(0);
scope.$digest();
// the listener is always called during the first $digest loop after it was registered
expect(scope.counter).toEqual(1);
scope.$digest();
// but now it will not be called unless the value changes
expect(scope.counter).toEqual(1);
scope.name = 'adam';
scope.$digest();
expect(scope.counter).toEqual(2);
// Using a function as a watchExpression
var food;
scope.foodCounter = 0;
expect(scope.foodCounter).toEqual(0);
scope.$watch(
// This function returns the value being watched. It is called for each turn of the $digest loop
function() { return food; },
// This is the change listener, called when the value returned from the above function changes
function(newValue, oldValue) {
if ( newValue !== oldValue ) {
// Only increment the counter if the value changed
scope.foodCounter = scope.foodCounter + 1;
}
}
);
// No digest has been run so the counter will be zero
expect(scope.foodCounter).toEqual(0);
// Run the digest but since food has not changed count will still be zero
scope.$digest();
expect(scope.foodCounter).toEqual(0);
// Update food and run digest. Now the counter will increment
food = 'cheeseburger';
scope.$digest();
expect(scope.foodCounter).toEqual(1);
Parameters
| Param | Type | Details |
|---|---|---|
| watchExpression | function()string | Expression that is evaluated on each $digest cycle. A change in the return value triggers a call to the
|
| listener | function(newVal, oldVal, scope) | Callback called whenever the value of
|
| objectEquality (optional) | boolean | Compare for object equality using (default: false) |
Returns
function() |
Returns a deregistration function for this listener. |
Please login to continue.