Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 25f008f

Browse files
jbedardpetebacondarwin
authored andcommitted
feat($parse): allow watching array/object of inputs to literal values
The inputs of array/object literals are now watched for changes. If the an input changes then a new instance of the literal will be provided when the parsed expression is executed. Closes #15301
1 parent 4a593db commit 25f008f

File tree

2 files changed

+72
-4
lines changed

2 files changed

+72
-4
lines changed

src/ng/parse.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1782,13 +1782,13 @@ function $ParseProvider() {
17821782
}
17831783
}
17841784

1785-
function expressionInputDirtyCheck(newValue, oldValueOfValue) {
1785+
function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) {
17861786

17871787
if (newValue == null || oldValueOfValue == null) { // null/undefined
17881788
return newValue === oldValueOfValue;
17891789
}
17901790

1791-
if (typeof newValue === 'object') {
1791+
if (typeof newValue === 'object' && !compareObjectIdentity) {
17921792

17931793
// attempt to convert the value to a primitive type
17941794
// TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
@@ -1817,7 +1817,7 @@ function $ParseProvider() {
18171817
inputExpressions = inputExpressions[0];
18181818
return scope.$watch(function expressionInputWatch(scope) {
18191819
var newInputValue = inputExpressions(scope);
1820-
if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {
1820+
if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, parsedExpression.literal)) {
18211821
lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
18221822
oldInputValueOf = newInputValue && getValueOf(newInputValue);
18231823
}
@@ -1837,7 +1837,7 @@ function $ParseProvider() {
18371837

18381838
for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
18391839
var newInputValue = inputExpressions[i](scope);
1840-
if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
1840+
if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], parsedExpression.literal))) {
18411841
oldInputValues[i] = newInputValue;
18421842
oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
18431843
}

test/ng/parseSpec.js

+68
Original file line numberDiff line numberDiff line change
@@ -3118,6 +3118,74 @@ describe('parser', function() {
31183118
scope.$digest();
31193119
expect(objB.value).toBe(scope.input);
31203120
}));
3121+
3122+
it('should support watching literals', inject(function($parse) {
3123+
var lastVal = NaN;
3124+
var callCount = 0;
3125+
var listener = function(val) { callCount++; lastVal = val; };
3126+
3127+
scope.$watch('{val: val}', listener);
3128+
3129+
scope.$apply('val = 1');
3130+
expect(callCount).toBe(1);
3131+
expect(lastVal).toEqual({val: 1});
3132+
3133+
scope.$apply('val = []');
3134+
expect(callCount).toBe(2);
3135+
expect(lastVal).toEqual({val: []});
3136+
3137+
scope.$apply('val = []');
3138+
expect(callCount).toBe(3);
3139+
expect(lastVal).toEqual({val: []});
3140+
3141+
scope.$apply('val = {}');
3142+
expect(callCount).toBe(4);
3143+
expect(lastVal).toEqual({val: {}});
3144+
}));
3145+
3146+
it('should only watch the direct inputs to literals', inject(function($parse) {
3147+
var lastVal = NaN;
3148+
var callCount = 0;
3149+
var listener = function(val) { callCount++; lastVal = val; };
3150+
3151+
scope.$watch('{val: val}', listener);
3152+
3153+
scope.$apply('val = 1');
3154+
expect(callCount).toBe(1);
3155+
expect(lastVal).toEqual({val: 1});
3156+
3157+
scope.$apply('val = [2]');
3158+
expect(callCount).toBe(2);
3159+
expect(lastVal).toEqual({val: [2]});
3160+
3161+
scope.$apply('val.push(3)');
3162+
expect(callCount).toBe(2);
3163+
3164+
scope.$apply('val.length = 0');
3165+
expect(callCount).toBe(2);
3166+
}));
3167+
3168+
it('should only watch the direct inputs to nested literals', inject(function($parse) {
3169+
var lastVal = NaN;
3170+
var callCount = 0;
3171+
var listener = function(val) { callCount++; lastVal = val; };
3172+
3173+
scope.$watch('[{val: [val]}]', listener);
3174+
3175+
scope.$apply('val = 1');
3176+
expect(callCount).toBe(1);
3177+
expect(lastVal).toEqual([{val: [1]}]);
3178+
3179+
scope.$apply('val = [2]');
3180+
expect(callCount).toBe(2);
3181+
expect(lastVal).toEqual([{val: [[2]]}]);
3182+
3183+
scope.$apply('val.push(3)');
3184+
expect(callCount).toBe(2);
3185+
3186+
scope.$apply('val.length = 0');
3187+
expect(callCount).toBe(2);
3188+
}));
31213189
});
31223190

31233191
describe('locals', function() {

0 commit comments

Comments
 (0)