Angular 1.5 enables the ability to multi transclude.
Notably, it'd be useful to be able to transclude a dynamic number of items into a directive and declare the names and locations of those transcludes at a later time (e.g. in the link/compile).
To further illustrate, I want the ability to do something like:
//Example usage of directive
<multi-slot-transclude-example>
<transclude1>TEST1</div>
<transclude2>TEST2</div>
<transclude3>TEST3</div>
<transclude4>TEST4</div>
.... dynamic number of items ...
</multi-slot-transclude-example>
//Example of directive that dynamically transcludes multiple items
angular.module("multiSlotTranscludeExample", [])
.directive("directiveName", function(){
return {
restrict: 'E',
transclude: {
't1': '?transclude1',
't2': '?transclude2',
//I'd like this list to be able to be defined non-statically (e.g. in link)
},
template: '<div ng-repeat="n in transcludedElementList">'
+ '<div ng-transclude="t{{n}"></div>'
+ '</div>'
};
})
Note that in the directive declaration which implements a multi-transclude, I have to have prior knowledge about the number of items that will be transcluded when declaring it.
Is there a way to do something like this in either a link (or using a workaround), which would keep the same functionality that transclusion current offers?
Unfortunately, Angular does not seem to provide any non-intrusive way to do this.
However, it can be achieved with a little tweak.
We need to intervene in angular.js's transclusion slot logic:
...
var slots = createMap();
$template = jqLite(jqLiteClone(compileNode)).contents();
// Small tweak to allow dynamic transclusion
if (directiveValue === 'dynamic') {
directiveValue = $parse(templateAttrs.transcludeDynamic)();
}
if (isObject(directiveValue)) {
// We have transclusion slots,
// collect them up, compile them and store their transclusion functions
$template = [];
...
This allows us to specify the transclusion options in the component's consumer, like so:
<my-custom-component transclude-dynamic="{testSlot: 'test', testSlot2: 'test2'}">
<test>something to transclude</test>
<test2>then another slot content to transclude</test2>
</my-custom-component>
In the component we enable dynamic transclusion:
...
selector: 'myCustomComponent',
template: template,
transclude: 'dynamic',
bindings: {
transcludeDynamic: '<'
}
Note that we also bind the transclusion info, this enables us to ng-repeat, ng-if and any other logic on it.
For example:
<div ng-repeat="(slot, name) in $ctrl.transcludeDynamic">
<div ng-transclude="{{slot}}"></div>
<hr>
<div>something else</div>
</div>
PR: https://github.com/angular/angular.js/pull/14227
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With