diff --git a/src/ng/directive/ngTransclude.js b/src/ng/directive/ngTransclude.js index c55537b2fdd0..5b31b06a2248 100644 --- a/src/ng/directive/ngTransclude.js +++ b/src/ng/directive/ngTransclude.js @@ -159,35 +159,45 @@ * */ var ngTranscludeMinErr = minErr('ngTransclude'); -var ngTranscludeDirective = ngDirective({ - restrict: 'EAC', - link: function($scope, $element, $attrs, controller, $transclude) { +var ngTranscludeDirective = ['$compile', function($compile) { + return { + restrict: 'EAC', + terminal: true, + link: function($scope, $element, $attrs, controller, $transclude) { + if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) { + // If the attribute is of the form: `ng-transclude="ng-transclude"` + // then treat it like the default + $attrs.ngTransclude = ''; + } - if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) { - // If the attribute is of the form: `ng-transclude="ng-transclude"` - // then treat it like the default - $attrs.ngTransclude = ''; - } + function ngTranscludeCloneAttachFn(clone, transcludedScope) { + if (clone.length) { + $element.empty(); + $element.append(clone); + } else { + // Since this is the fallback content rather than the transcluded content, + // we compile against the scope we were linked against rather than the transcluded + // scope since this is the directive's own content + $compile($element.contents())($scope); - function ngTranscludeCloneAttachFn(clone) { - if (clone.length) { - $element.empty(); - $element.append(clone); + // There is nothing linked against the transcluded scope since no content was available, + // so it should be safe to clean up the generated scope. + transcludedScope.$destroy(); + } } - } - if (!$transclude) { - throw ngTranscludeMinErr('orphan', - 'Illegal use of ngTransclude directive in the template! ' + - 'No parent directive that requires a transclusion found. ' + - 'Element: {0}', - startingTag($element)); - } - - // If there is no slot name defined or the slot name is not optional - // then transclude the slot - var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot; - $transclude(ngTranscludeCloneAttachFn, null, slotName); - } -}); + if (!$transclude) { + throw ngTranscludeMinErr('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + // If there is no slot name defined or the slot name is not optional + // then transclude the slot + var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot; + $transclude(ngTranscludeCloneAttachFn, null, slotName); + } + }; +}]; diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index dde7eeb4df8d..99feac76b00a 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -7937,11 +7937,23 @@ describe('$compile', function() { it('should clear contents of the ng-translude element before appending transcluded content' + ' if transcluded content exists', function() { + var contentsDidLink = false; + module(function() { + directive('inner', function() { + return { + restrict: 'E', + template: 'old stuff! ', + link: function() { + contentsDidLink = true; + } + }; + }); + directive('trans', function() { return { transclude: true, - template: '
old stuff!
' + template: '
' }; }); }); @@ -7949,23 +7961,37 @@ describe('$compile', function() { element = $compile('
unicorn!
')($rootScope); $rootScope.$apply(); expect(sortedHtml(element.html())).toEqual('
unicorn!
'); + expect(contentsDidLink).toBe(false); }); }); it('should NOT clear contents of the ng-translude element before appending transcluded content' + ' if transcluded content does NOT exist', function() { + var contentsDidLink = false; + module(function() { + directive('inner', function() { + return { + restrict: 'E', + template: 'old stuff! ', + link: function() { + contentsDidLink = true; + } + }; + }); + directive('trans', function() { return { transclude: true, - template: '
old stuff!
' + template: '
' }; }); }); inject(function(log, $rootScope, $compile) { element = $compile('
')($rootScope); $rootScope.$apply(); - expect(sortedHtml(element.html())).toEqual('
old stuff!
'); + expect(sortedHtml(element.html())).toEqual('
old stuff!
'); + expect(contentsDidLink).toBe(true); }); });