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

Commit ede0e0a

Browse files
fix(ngTransclude): ensure that fallback only appears and is compiled when needed
1 parent df53955 commit ede0e0a

File tree

1 file changed

+43
-30
lines changed

1 file changed

+43
-30
lines changed

src/ng/directive/ngTransclude.js

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -163,41 +163,54 @@ var ngTranscludeDirective = ['$compile', function($compile) {
163163
return {
164164
restrict: 'EAC',
165165
terminal: true,
166-
link: function($scope, $element, $attrs, controller, $transclude) {
167-
if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {
168-
// If the attribute is of the form: `ng-transclude="ng-transclude"`
169-
// then treat it like the default
170-
$attrs.ngTransclude = '';
171-
}
166+
compile: function ngTranscludeCompile(tElement, tAttrs) {
167+
// Remove and cache any original content to act as a fallback
168+
var fallbackContents = tElement.contents();
169+
tElement.empty();
172170

173-
function ngTranscludeCloneAttachFn(clone, transcludedScope) {
174-
if (clone.length) {
175-
$element.empty();
176-
$element.append(clone);
177-
} else {
178-
// Since this is the fallback content rather than the transcluded content,
179-
// we compile against the scope we were linked against rather than the transcluded
180-
// scope since this is the directive's own content
181-
$compile($element.contents())($scope);
171+
return function ngTranscludePostLink($scope, $element, $attrs, controller, $transclude) {
172+
if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {
173+
// If the attribute is of the form: `ng-transclude="ng-transclude"`
174+
// then treat it like the default
175+
$attrs.ngTransclude = '';
176+
}
182177

183-
// There is nothing linked against the transcluded scope since no content was available,
184-
// so it should be safe to clean up the generated scope.
185-
transcludedScope.$destroy();
178+
function ngTranscludeCloneAttachFn(clone, transcludedScope) {
179+
if (clone.length) {
180+
$element.append(clone);
181+
} else {
182+
if (fallbackContents.length) {
183+
// Since this is the fallback content rather than the transcluded content,
184+
// we compile against the scope we were linked against rather than the transcluded
185+
// scope since this is the directive's own content
186+
$element.append(fallbackContents);
187+
$compile(fallbackContents)($scope);
188+
}
189+
// There is nothing linked against the transcluded scope since no content was available,
190+
// so it should be safe to clean up the generated scope.
191+
transcludedScope.$destroy();
192+
}
186193
}
187-
}
188194

189-
if (!$transclude) {
190-
throw ngTranscludeMinErr('orphan',
191-
'Illegal use of ngTransclude directive in the template! ' +
192-
'No parent directive that requires a transclusion found. ' +
193-
'Element: {0}',
194-
startingTag($element));
195-
}
195+
if (!$transclude) {
196+
throw ngTranscludeMinErr('orphan',
197+
'Illegal use of ngTransclude directive in the template! ' +
198+
'No parent directive that requires a transclusion found. ' +
199+
'Element: {0}',
200+
startingTag($element));
201+
}
196202

197-
// If there is no slot name defined or the slot name is not optional
198-
// then transclude the slot
199-
var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;
200-
$transclude(ngTranscludeCloneAttachFn, null, slotName);
203+
// If there is no slot name defined or the slot name is not optional
204+
// then transclude the slot
205+
var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;
206+
$transclude(ngTranscludeCloneAttachFn, null, slotName);
207+
if (slotName && !$transclude.isSlotFilled(slotName)) {
208+
// The slot was optional and no transclusion content was provided
209+
// so we just compile and use the fallbackContents
210+
$element.append(fallbackContents);
211+
$compile(fallbackContents)($scope);
212+
}
213+
};
201214
}
202215
};
203216
}];

0 commit comments

Comments
 (0)