fix($compile): don't pass transclude to template of non-transclude directive
If a directive provides a template but is not explicitly requesting transclusion then the compiler should not pass a transclusion function to the directives within the template.
This commit is contained in:
committed by
Caitlin Potter
parent
6f1d9f8ca6
commit
eafba9e2e5
+17
-8
@@ -907,7 +907,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
!childNodes.length)
|
!childNodes.length)
|
||||||
? null
|
? null
|
||||||
: compileNodes(childNodes,
|
: compileNodes(childNodes,
|
||||||
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
|
nodeLinkFn ? (
|
||||||
|
(nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
|
||||||
|
&& nodeLinkFn.transclude) : transcludeFn);
|
||||||
|
|
||||||
linkFns.push(nodeLinkFn, childLinkFn);
|
linkFns.push(nodeLinkFn, childLinkFn);
|
||||||
linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
|
linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
|
||||||
@@ -942,14 +944,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
childScope = scope;
|
childScope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to create a new boundTranscludeFn if
|
if ( nodeLinkFn.transcludeOnThisElement ) {
|
||||||
// - a directive on this element wants to transclude
|
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
|
||||||
// or
|
|
||||||
// - there is no parentBoundTranscludeFn already and a transcludeFn was passed in
|
} else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
|
||||||
if ( nodeLinkFn.transcludeOnThisElement || (!parentBoundTranscludeFn && transcludeFn) ) {
|
|
||||||
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn, parentBoundTranscludeFn);
|
|
||||||
} else {
|
|
||||||
childBoundTranscludeFn = parentBoundTranscludeFn;
|
childBoundTranscludeFn = parentBoundTranscludeFn;
|
||||||
|
|
||||||
|
} else if (!parentBoundTranscludeFn && transcludeFn) {
|
||||||
|
childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
childBoundTranscludeFn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
|
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
|
||||||
@@ -1164,6 +1169,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
templateDirective = previousCompileContext.templateDirective,
|
templateDirective = previousCompileContext.templateDirective,
|
||||||
nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
|
nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
|
||||||
hasTranscludeDirective = false,
|
hasTranscludeDirective = false,
|
||||||
|
hasTemplate = false,
|
||||||
hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
|
hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
|
||||||
$compileNode = templateAttrs.$$element = jqLite(compileNode),
|
$compileNode = templateAttrs.$$element = jqLite(compileNode),
|
||||||
directive,
|
directive,
|
||||||
@@ -1254,6 +1260,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (directive.template) {
|
if (directive.template) {
|
||||||
|
hasTemplate = true;
|
||||||
assertNoDuplicate('template', templateDirective, directive, $compileNode);
|
assertNoDuplicate('template', templateDirective, directive, $compileNode);
|
||||||
templateDirective = directive;
|
templateDirective = directive;
|
||||||
|
|
||||||
@@ -1303,6 +1310,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (directive.templateUrl) {
|
if (directive.templateUrl) {
|
||||||
|
hasTemplate = true;
|
||||||
assertNoDuplicate('template', templateDirective, directive, $compileNode);
|
assertNoDuplicate('template', templateDirective, directive, $compileNode);
|
||||||
templateDirective = directive;
|
templateDirective = directive;
|
||||||
|
|
||||||
@@ -1340,6 +1348,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
|
|
||||||
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
|
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
|
||||||
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
|
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
|
||||||
|
nodeLinkFn.templateOnThisElement = hasTemplate;
|
||||||
nodeLinkFn.transclude = childTranscludeFn;
|
nodeLinkFn.transclude = childTranscludeFn;
|
||||||
|
|
||||||
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
|
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
|
||||||
|
|||||||
@@ -3764,6 +3764,39 @@ describe('$compile', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should not pass transclusion into a template directive when the directive didn\'t request transclusion', function() {
|
||||||
|
|
||||||
|
module(function($compileProvider) {
|
||||||
|
|
||||||
|
$compileProvider.directive('transFoo', valueFn({
|
||||||
|
template: '<div>' +
|
||||||
|
'<div no-trans-bar></div>' +
|
||||||
|
'<div ng-transclude>this one should get replaced with content</div>' +
|
||||||
|
'<div class="foo" ng-transclude></div>' +
|
||||||
|
'</div>',
|
||||||
|
transclude: true
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
$compileProvider.directive('noTransBar', valueFn({
|
||||||
|
template: '<div>' +
|
||||||
|
// This ng-transclude is invalid. It should throw an error.
|
||||||
|
'<div class="bar" ng-transclude></div>' +
|
||||||
|
'</div>',
|
||||||
|
transclude: false
|
||||||
|
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
inject(function($compile, $rootScope) {
|
||||||
|
expect(function() {
|
||||||
|
$compile('<div trans-foo>content</div>')($rootScope);
|
||||||
|
}).toThrowMinErr('ngTransclude', 'orphan',
|
||||||
|
'Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: <div class="bar" ng-transclude="">');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should make the result of a transclusion available to the parent directive in post-linking phase' +
|
it('should make the result of a transclusion available to the parent directive in post-linking phase' +
|
||||||
'(template)', function() {
|
'(template)', function() {
|
||||||
module(function() {
|
module(function() {
|
||||||
|
|||||||
Reference in New Issue
Block a user