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

Commit 4785304

Browse files
feat(ngTransclude): don't overwrite the contents with an unfilled optional slot
Previously the contents of the `ngTransclude` element would always be emptied, even if there was no transclusion to replace it. Now, optional slots that have not been filled with content will not cause the `ngTransclude` contents to be emptied. Closes #13426
1 parent 7f3d5f9 commit 4785304

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/ng/directive/ngTransclude.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
* You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name
1212
* as the value of the `ng-transclude` or `ng-transclude-slot` attribute.
1313
*
14-
* Any existing content of the element that this directive is placed on, will be removed before the transcluded content is inserted.
14+
* For required slots and the default transclusion, existing content will be removed before the transcluded content is inserted.
15+
*
16+
* For optional slots, existing content is left in place, if the slot was not filled.
1517
*
1618
* @element ANY
1719
*
@@ -81,11 +83,13 @@
8183
restrict: 'E',
8284
transclude: {
8385
'paneTitle': '?title',
84-
'paneBody': 'body'
86+
'paneBody': 'body',
87+
'paneFooter': '?footer'
8588
},
8689
template: '<div style="border: 1px solid black;">' +
8790
'<div ng-transclude="title" style="background-color: gray"></div>' +
8891
'<div ng-transclude="body"></div>' +
92+
'<div ng-transclude="footer" style="background-color: gray">Default Footer</div>' +
8993
'</div>'
9094
};
9195
})
@@ -132,7 +136,12 @@ var ngTranscludeDirective = ngDirective({
132136
startingTag($element));
133137
}
134138

135-
$transclude(ngTranscludeCloneAttachFn, null, $attrs.ngTransclude || $attrs.ngTranscludeSlot);
139+
// If there is no slot name defined or the slot name is not optional
140+
// then transclude the slot
141+
var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;
142+
if (!slotName || $transclude.$slots[slotName] !== null) {
143+
$transclude(ngTranscludeCloneAttachFn, null, slotName);
144+
}
136145
}
137146
});
138147

test/ng/compileSpec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8030,6 +8030,37 @@ describe('$compile', function() {
80308030
expect(capturedTranscludeFn.$slots.bossSlot).toBe(null);
80318031
});
80328032
});
8033+
8034+
it('should not overwrite the contents of an `ng-transclude` element, if the matching optional slot is not filled', function() {
8035+
module(function() {
8036+
directive('minionComponent', function() {
8037+
return {
8038+
restrict: 'E',
8039+
scope: {},
8040+
transclude: {
8041+
minion: 'minionSlot',
8042+
boss: '?bossSlot'
8043+
},
8044+
template:
8045+
'<div class="boss" ng-transclude="bossSlot">default boss content</div>' +
8046+
'<div class="minion" ng-transclude="minionSlot">default minion content</div>' +
8047+
'<div class="other" ng-transclude>default content</div>'
8048+
};
8049+
});
8050+
});
8051+
inject(function($rootScope, $compile) {
8052+
element = $compile(
8053+
'<minion-component>' +
8054+
'<minion>stuart</minion>' +
8055+
'<span>dorothy</span>' +
8056+
'<minion>kevin</minion>' +
8057+
'</minion-component>')($rootScope);
8058+
$rootScope.$apply();
8059+
expect(element.children().eq(0).text()).toEqual('default boss content');
8060+
expect(element.children().eq(1).text()).toEqual('stuartkevin');
8061+
expect(element.children().eq(2).text()).toEqual('dorothy');
8062+
});
8063+
});
80338064
});
80348065

80358066

0 commit comments

Comments
 (0)