Skip to content

Commit

Permalink
fix($compile): reference local in isolate scope
Browse files Browse the repository at this point in the history
This was really corner case:
Watcher needs to return changed value, to notify that model might have changed and one more $digest cycle needs to be performed.

The watcher, that takes care of reference binding into an isolate scope ("="), did not return changed value, if the change was from the isolate scope to the parent.

If any other watcher returned change, it worked fine, as this change caused re-digest.

Closes angular#1272
  • Loading branch information
vojtajina committed Sep 13, 2012
1 parent b0a05a7 commit a875b0b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ function $CompileProvider($provide) {
lastValue = scope[scopeName] = parentValue;
} else {
// if the parent can be assigned then do so
parentSet(parentScope, lastValue = scope[scopeName]);
parentSet(parentScope, parentValue = lastValue = scope[scopeName]);
}
}
return parentValue;
Expand Down
19 changes: 19 additions & 0 deletions test/ng/compileSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,7 @@ describe('$compile', function() {
attrAlias: '@attr',
ref: '=',
refAlias: '= ref',
reference: '=',

This comment has been minimized.

Copy link
@IgorMinar

IgorMinar Sep 18, 2012

you already have ref on line 1710, why not use that one?

This comment has been minimized.

Copy link
@vojtajina

vojtajina Sep 21, 2012

Author Owner

Nope, that wouldn't cover this corner case.

The ref is bound twice (once into scope.ref and then to scope.refAlias).

1/ you change isolateScope.reference to "new"
2/ watcher triggers and parentScope.name is updated with the "new" value
HERE WAS THE BUG, that in this corner case, first watcher function returned the old (non-updated value), even though it did update the value. And therefore angular did not another $digest, because it thought nothing has changed. So any watcher registered before this "isolate scope syncing watcher" would not fire.

If there is another watcher on this property (refAlias), this watcher triggers update from parent into isolateScope.refAlias and that makes model dirty, therefore another $digest cycle and therefore everything works fine.

Sorry, it's difficult to explain this, it's really special corner case, that you can't easily get into.

expr: '&',
exprAlias: '&expr'
},
Expand Down Expand Up @@ -1830,6 +1831,24 @@ describe('$compile', function() {
$rootScope.$apply();
expect(componentScope.ref).toBe('hello misko');
}));

// regression
it('should stabilize model', inject(function() {
compile('<div><span my-component reference="name">');

var lastRefValueInParent;
$rootScope.$watch('name', function(ref) {
lastRefValueInParent = ref;
});

$rootScope.name = 'aaa';
$rootScope.$apply();

componentScope.reference = 'new';
$rootScope.$apply();

expect(lastRefValueInParent).toBe('new');
}));
});


Expand Down

1 comment on commit a875b0b

@IgorMinar
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise this looks good to me.

Please sign in to comment.