fix($compile): only pass isolate scope to children that belong to the isolate directive

I had to fix one unit test, as it assumed the broken behavior, where application template gets the
isolate scope of other (isolate) directive, rather than the regular scope.

BREAKING CHANGE: Child elements that are defined either in the application template or in some other
directives template do not get the isolate scope. In theory, nobody should rely on this behavior, as
it is very rare - in most cases the isolate directive has a template.
This commit is contained in:
Vojta Jina 2013-11-05 12:27:56 -08:00 committed by Igor Minar
parent 909cabd36d
commit d0efd5eefc
2 changed files with 65 additions and 4 deletions

View file

@ -1480,8 +1480,13 @@ function $CompileProvider($provide) {
}
// RECURSION
// TODO(vojta): only pass isolate if the isolate directive has template
childLinkFn && childLinkFn(isolateScope || scope, linkNode.childNodes, undefined, boundTranscludeFn);
// We only pass the isolate scope, if the isolate directive has a template,
// otherwise the child elements do not belong to the isolate directive.
var scopeToChild = scope;
if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
scopeToChild = isolateScope;
}
childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
// POSTLINKING
for(i = postLinkFns.length - 1; i >= 0; i--) {

View file

@ -1426,7 +1426,7 @@ describe('$compile', function() {
return {
restrict: 'CA',
link: {pre: function(scope) {
log('log-' + scope.$id + '-' + scope.$parent.$id);
log('log-' + scope.$id + '-' + (scope.$parent && scope.$parent.$id || 'no-parent'));
}}
};
});
@ -1443,7 +1443,7 @@ describe('$compile', function() {
it('should allow creation of new isolated scopes for directives', inject(
function($rootScope, $compile, log) {
element = $compile('<div><span iscope><a log></a></span></div>')($rootScope);
expect(log).toEqual('log-002-001; LOG; 002');
expect(log).toEqual('log-001-no-parent; LOG; 002');
$rootScope.name = 'abc';
expect(iscope.$parent).toBe($rootScope);
expect(iscope.name).toBeUndefined();
@ -2131,6 +2131,62 @@ describe('$compile', function() {
expect(componentScope.$parent).toBe(regularScope)
}));
it('should not give the isolate scope to other directive template', function() {
module(function() {
directive('otherTplDir', function() {
return {
template: 'value: {{value}}'
};
});
});
inject(function($rootScope) {
compile('<div my-component other-tpl-dir>');
$rootScope.$apply(function() {
$rootScope.value = 'from-parent';
});
expect(element.html()).toBe('value: from-parent');
});
});
it('should not give the isolate scope to other directive template (with templateUrl)', function() {
module(function() {
directive('otherTplDir', function() {
return {
templateUrl: 'other.html'
};
});
});
inject(function($rootScope, $templateCache) {
$templateCache.put('other.html', 'value: {{value}}')
compile('<div my-component other-tpl-dir>');
$rootScope.$apply(function() {
$rootScope.value = 'from-parent';
});
expect(element.html()).toBe('value: from-parent');
});
});
it('should not give the isolate scope to regular child elements', function() {
inject(function($rootScope) {
compile('<div my-component>value: {{value}}</div>');
$rootScope.$apply(function() {
$rootScope.value = 'from-parent';
});
expect(element.html()).toBe('value: from-parent');
});
});
describe('attribute', function() {
it('should copy simple attribute', inject(function() {
compile('<div><span my-component attr="some text">');