diff --git a/src/ng/compile.js b/src/ng/compile.js
index bc1cae5bfca6..f26c60f57772 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -3508,21 +3508,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (optional && !attrs[attrName]) break;
parentGet = $parse(attrs[attrName]);
- var deepWatch = parentGet.literal;
+ var isLiteral = parentGet.literal;
var initialValue = destination[scopeName] = parentGet(scope);
initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {
if (oldValue === newValue) {
- if (oldValue === initialValue || (deepWatch && equals(oldValue, initialValue))) {
+ if (oldValue === initialValue || (isLiteral && equals(oldValue, initialValue))) {
return;
}
oldValue = initialValue;
}
recordChanges(scopeName, newValue, oldValue);
destination[scopeName] = newValue;
- }, deepWatch);
+ });
removeWatchCollection.push(removeWatch);
break;
diff --git a/src/ng/parse.js b/src/ng/parse.js
index 3e2661e16f6d..91cfcf9d4ba3 100644
--- a/src/ng/parse.js
+++ b/src/ng/parse.js
@@ -1786,13 +1786,13 @@ function $ParseProvider() {
}
}
- function expressionInputDirtyCheck(newValue, oldValueOfValue) {
+ function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) {
if (newValue == null || oldValueOfValue == null) { // null/undefined
return newValue === oldValueOfValue;
}
- if (typeof newValue === 'object') {
+ if (typeof newValue === 'object' && !compareObjectIdentity) {
// attempt to convert the value to a primitive type
// TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
@@ -1821,7 +1821,7 @@ function $ParseProvider() {
inputExpressions = inputExpressions[0];
return scope.$watch(function expressionInputWatch(scope) {
var newInputValue = inputExpressions(scope);
- if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {
+ if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, parsedExpression.literal)) {
lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
oldInputValueOf = newInputValue && getValueOf(newInputValue);
}
@@ -1841,7 +1841,7 @@ function $ParseProvider() {
for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
var newInputValue = inputExpressions[i](scope);
- if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
+ if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], parsedExpression.literal))) {
oldInputValues[i] = newInputValue;
oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
}
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 544baf8a74ca..35e174845ee4 100755
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -4259,6 +4259,78 @@ describe('$compile', function() {
});
+ it('should trigger `$onChanges` for literal expressions when expression input value changes (simple value)', function() {
+ var log = [];
+ function TestController() { }
+ TestController.prototype.$onChanges = function(change) { log.push(change); };
+
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: { 'prop1': '<' }
+ });
+
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('