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

Commit eafba9e

Browse files
petebacondarwincaitp
authored andcommitted
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.
1 parent 6f1d9f8 commit eafba9e

File tree

2 files changed

+50
-8
lines changed

2 files changed

+50
-8
lines changed

src/ng/compile.js

+17-8
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
907907
!childNodes.length)
908908
? null
909909
: compileNodes(childNodes,
910-
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
910+
nodeLinkFn ? (
911+
(nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
912+
&& nodeLinkFn.transclude) : transcludeFn);
911913

912914
linkFns.push(nodeLinkFn, childLinkFn);
913915
linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
@@ -942,14 +944,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
942944
childScope = scope;
943945
}
944946

945-
// We need to create a new boundTranscludeFn if
946-
// - a directive on this element wants to transclude
947-
// or
948-
// - there is no parentBoundTranscludeFn already and a transcludeFn was passed in
949-
if ( nodeLinkFn.transcludeOnThisElement || (!parentBoundTranscludeFn && transcludeFn) ) {
950-
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn, parentBoundTranscludeFn);
951-
} else {
947+
if ( nodeLinkFn.transcludeOnThisElement ) {
948+
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
949+
950+
} else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
952951
childBoundTranscludeFn = parentBoundTranscludeFn;
952+
953+
} else if (!parentBoundTranscludeFn && transcludeFn) {
954+
childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
955+
956+
} else {
957+
childBoundTranscludeFn = null;
953958
}
954959

955960
nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
@@ -1164,6 +1169,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
11641169
templateDirective = previousCompileContext.templateDirective,
11651170
nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
11661171
hasTranscludeDirective = false,
1172+
hasTemplate = false,
11671173
hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
11681174
$compileNode = templateAttrs.$$element = jqLite(compileNode),
11691175
directive,
@@ -1254,6 +1260,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
12541260
}
12551261

12561262
if (directive.template) {
1263+
hasTemplate = true;
12571264
assertNoDuplicate('template', templateDirective, directive, $compileNode);
12581265
templateDirective = directive;
12591266

@@ -1303,6 +1310,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13031310
}
13041311

13051312
if (directive.templateUrl) {
1313+
hasTemplate = true;
13061314
assertNoDuplicate('template', templateDirective, directive, $compileNode);
13071315
templateDirective = directive;
13081316

@@ -1340,6 +1348,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13401348

13411349
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
13421350
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
1351+
nodeLinkFn.templateOnThisElement = hasTemplate;
13431352
nodeLinkFn.transclude = childTranscludeFn;
13441353

13451354
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;

test/ng/compileSpec.js

+33
Original file line numberDiff line numberDiff line change
@@ -3764,6 +3764,39 @@ describe('$compile', function() {
37643764
});
37653765

37663766

3767+
it('should not pass transclusion into a template directive when the directive didn\'t request transclusion', function() {
3768+
3769+
module(function($compileProvider) {
3770+
3771+
$compileProvider.directive('transFoo', valueFn({
3772+
template: '<div>' +
3773+
'<div no-trans-bar></div>' +
3774+
'<div ng-transclude>this one should get replaced with content</div>' +
3775+
'<div class="foo" ng-transclude></div>' +
3776+
'</div>',
3777+
transclude: true
3778+
3779+
}));
3780+
3781+
$compileProvider.directive('noTransBar', valueFn({
3782+
template: '<div>' +
3783+
// This ng-transclude is invalid. It should throw an error.
3784+
'<div class="bar" ng-transclude></div>' +
3785+
'</div>',
3786+
transclude: false
3787+
3788+
}));
3789+
});
3790+
3791+
inject(function($compile, $rootScope) {
3792+
expect(function() {
3793+
$compile('<div trans-foo>content</div>')($rootScope);
3794+
}).toThrowMinErr('ngTransclude', 'orphan',
3795+
'Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: <div class="bar" ng-transclude="">');
3796+
});
3797+
});
3798+
3799+
37673800
it('should make the result of a transclusion available to the parent directive in post-linking phase' +
37683801
'(template)', function() {
37693802
module(function() {

0 commit comments

Comments
 (0)