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

Commit 4a0bd6c

Browse files
fix($compile): still trigger $onChanges even if the inner value already matches the new value
Closes #14406
1 parent 5d695e5 commit 4a0bd6c

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/ng/compile.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -3197,10 +3197,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
31973197
destination[scopeName] = parentGet(scope);
31983198
initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);
31993199

3200-
removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newParentValue) {
3201-
var oldValue = destination[scopeName];
3202-
recordChanges(scopeName, newParentValue, oldValue);
3203-
destination[scopeName] = newParentValue;
3200+
removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {
3201+
if (newValue === oldValue) {
3202+
// If the new and old values are identical then this is the first time the watch has been triggered
3203+
// So instead we use the current value on the destination as the old value
3204+
oldValue = destination[scopeName];
3205+
}
3206+
recordChanges(scopeName, newValue, oldValue);
3207+
destination[scopeName] = newValue;
32043208
}, parentGet.literal);
32053209

32063210
removeWatchCollection.push(removeWatch);
@@ -3233,7 +3237,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
32333237
onChangesQueue.push(triggerOnChangesHook);
32343238
}
32353239
// If the has been a change on this property already then we need to reuse the previous value
3236-
if (changes[key]) {
3240+
if (isDefined(changes[key])) {
32373241
previousValue = changes[key].previousValue;
32383242
}
32393243
// Store this change

test/ng/compileSpec.js

+25
Original file line numberDiff line numberDiff line change
@@ -3742,6 +3742,31 @@ describe('$compile', function() {
37423742
});
37433743

37443744

3745+
it('should trigger `$onChanges` even if the inner value already equals the new outer value', function() {
3746+
var log = [];
3747+
function TestController() { }
3748+
TestController.prototype.$onChanges = function(change) { log.push(change); };
3749+
3750+
angular.module('my', [])
3751+
.component('c1', {
3752+
controller: TestController,
3753+
bindings: { 'prop1': '<' }
3754+
});
3755+
3756+
module('my');
3757+
inject(function($compile, $rootScope) {
3758+
element = $compile('<c1 prop1="val"></c1>')($rootScope);
3759+
3760+
$rootScope.$apply('val = 1');
3761+
expect(log.pop()).toEqual({prop1: jasmine.objectContaining({previousValue: undefined, currentValue: 1})});
3762+
3763+
element.isolateScope().$ctrl.prop1 = 2;
3764+
$rootScope.$apply('val = 2');
3765+
expect(log.pop()).toEqual({prop1: jasmine.objectContaining({previousValue: 1, currentValue: 2})});
3766+
});
3767+
});
3768+
3769+
37453770
it('should pass the original value as `previousValue` even if there were multiple changes in a single digest', function() {
37463771
var log = [];
37473772
function TestController() { }

0 commit comments

Comments
 (0)