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

Commit

Permalink
fix($compile): don't pass transclude to template of non-transclude di…
Browse files Browse the repository at this point in the history
…rective

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.
  • Loading branch information
petebacondarwin authored and vojtajina committed May 29, 2014
1 parent 6e15462 commit 19af039
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
25 changes: 17 additions & 8 deletions src/ng/compile.js
Expand Up @@ -924,7 +924,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
!childNodes.length)
? null
: compileNodes(childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
nodeLinkFn ? (
(nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
&& nodeLinkFn.transclude) : transcludeFn);

linkFns.push(nodeLinkFn, childLinkFn);
linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
Expand Down Expand Up @@ -959,14 +961,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
childScope = scope;
}

// We need to create a new boundTranscludeFn if
// - a directive on this element wants to transclude
// or
// - there is no parentBoundTranscludeFn already and a transcludeFn was passed in
if ( nodeLinkFn.transcludeOnThisElement || (!parentBoundTranscludeFn && transcludeFn) ) {
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn, parentBoundTranscludeFn);
} else {
if ( nodeLinkFn.transcludeOnThisElement ) {
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);

} else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
childBoundTranscludeFn = parentBoundTranscludeFn;

} else if (!parentBoundTranscludeFn && transcludeFn) {
childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);

} else {
childBoundTranscludeFn = null;
}

nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
Expand Down Expand Up @@ -1181,6 +1186,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
templateDirective = previousCompileContext.templateDirective,
nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
hasTranscludeDirective = false,
hasTemplate = false,
hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
$compileNode = templateAttrs.$$element = jqLite(compileNode),
directive,
Expand Down Expand Up @@ -1271,6 +1277,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}

if (directive.template) {
hasTemplate = true;
assertNoDuplicate('template', templateDirective, directive, $compileNode);
templateDirective = directive;

Expand Down Expand Up @@ -1320,6 +1327,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}

if (directive.templateUrl) {
hasTemplate = true;
assertNoDuplicate('template', templateDirective, directive, $compileNode);
templateDirective = directive;

Expand Down Expand Up @@ -1357,6 +1365,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {

nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
nodeLinkFn.templateOnThisElement = hasTemplate;
nodeLinkFn.transclude = childTranscludeFn;

previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
Expand Down
33 changes: 33 additions & 0 deletions test/ng/compileSpec.js
Expand Up @@ -3988,6 +3988,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' +
'(template)', function() {
module(function() {
Expand Down

0 comments on commit 19af039

Please sign in to comment.