Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4a3a578

Browse files
committedNov 17, 2014
feat($rootScope): Add custom compare and copy functions to $watch
Closes #10069
1 parent a9352c1 commit 4a3a578

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed
 

Diff for: ‎src/ng/rootScope.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,13 @@ function $RootScopeProvider() {
353353
* - `newVal` contains the current value of the `watchExpression`
354354
* - `oldVal` contains the previous value of the `watchExpression`
355355
* - `scope` refers to the current scope
356-
* @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
357-
* comparing for reference equality.
356+
* @param {boolean=|function()} objectEquality Compare for object equality using {@link angular.equals} instead of
357+
* comparing for reference equality. If a function is passed, it will be used as a replacement for {@link angular.equals}.
358+
* @param {function()} copier Replacement function for {@link angular.copy} to save value into oldVal for next
359+
change event.
358360
* @returns {function()} Returns a deregistration function for this listener.
359361
*/
360-
$watch: function(watchExp, listener, objectEquality) {
362+
$watch: function(watchExp, listener, objectEquality, copier) {
361363
var get = $parse(watchExp);
362364

363365
if (get.$$watchDelegate) {
@@ -375,6 +377,14 @@ function $RootScopeProvider() {
375377

376378
lastDirtyWatch = null;
377379

380+
if (isFunction(objectEquality)) {
381+
watcher.comparator = objectEquality;
382+
}
383+
384+
if (isFunction(copier)) {
385+
watcher.copier = copier;
386+
}
387+
378388
if (!isFunction(listener)) {
379389
watcher.fn = noop;
380390
}
@@ -763,12 +773,12 @@ function $RootScopeProvider() {
763773
if (watch) {
764774
if ((value = watch.get(current)) !== (last = watch.last) &&
765775
!(watch.eq
766-
? equals(value, last)
776+
? (watch.comparator ? watch.comparator(value, last) : equals(value, last))
767777
: (typeof value === 'number' && typeof last === 'number'
768778
&& isNaN(value) && isNaN(last)))) {
769779
dirty = true;
770780
lastDirtyWatch = watch;
771-
watch.last = watch.eq ? copy(value, null) : value;
781+
watch.last = watch.eq ? (watch.copier ? watch.copier(value, null) : copy(value, null)) : value;
772782
watch.fn(value, ((last === initWatchVal) ? value : last), current);
773783
if (ttl < 5) {
774784
logIdx = 4 - ttl;

Diff for: ‎test/ng/rootScopeSpec.js

+61
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,67 @@ describe('Scope', function() {
458458
expect(log).toEqual([]);
459459
}));
460460

461+
it('should use custom equality and copier',
462+
inject(function($rootScope) {
463+
var log = [];
464+
var oldLog = [];
465+
466+
function logger(newVal, oldVal) {
467+
var val = (newVal === oldVal || (newVal !== oldVal && oldVal !== newVal)) ? newVal : 'xxx';
468+
log.push(val);
469+
}
470+
471+
function oldLogger(newVal, oldVal) {
472+
var val = (newVal === oldVal || (newVal !== oldVal && oldVal !== newVal)) ? oldVal : 'xxx';
473+
oldLog.push(val);
474+
}
475+
476+
var watched = "ABC";
477+
var watchedFn = function() {
478+
return watched;
479+
};
480+
481+
// Comparator returns true if string starts with same character
482+
var comparator = function(newVal, oldVal) {
483+
if (oldVal === newVal) return true;
484+
if (oldVal === undefined || newVal === undefined) return false;
485+
if (newVal.length === oldVal.length === 0) return true;
486+
if (newVal.length > 0 && oldVal.length > 0 && oldVal[0] === newVal[0]) {
487+
return true;
488+
}
489+
return false;
490+
};
491+
492+
// Copier add " copy" to value
493+
var copier = function(value) {
494+
if (value !== undefined) {
495+
return value + " copy";
496+
}
497+
return undefined;
498+
};
499+
500+
$rootScope.$watch(watchedFn, logger, comparator, copier);
501+
$rootScope.$watch(watchedFn, oldLogger, comparator, copier);
502+
503+
$rootScope.$digest();
504+
expect(log).toEqual(['ABC']);
505+
expect(oldLog).toEqual(['ABC']);
506+
log = [];
507+
oldLog = [];
508+
509+
watched = "DEF";
510+
$rootScope.$digest();
511+
expect(log).toEqual(['DEF']);
512+
expect(oldLog).toEqual(['ABC copy']);
513+
log = [];
514+
oldLog = [];
515+
516+
watched = "DZZ";
517+
$rootScope.$digest();
518+
expect(log).toEqual([]);
519+
expect(oldLog).toEqual([]);
520+
}));
521+
461522

462523
describe('$watch deregistration', function() {
463524

0 commit comments

Comments
 (0)
This repository has been archived.