Skip to content

Commit

Permalink
Extract multi-transclude workaround into directive
Browse files Browse the repository at this point in the history
The `multi-transclude` attribute directive encapsulates the angular 1.4
workaround for multiple transclusion targets pioneered in `kbn-top-nav`
for separation of concerns and re-use.

There are some differences to the implementation in `kbn-top-nav`:
* The directive logic is completely contained inside the link function
  and therefore won't interfere with other controllers.
* The slots are declared as the attribute value.
* The transcluded items are appended to the transclusion target's
  children instead of replacing the whole target. This preserves the
  attributes present on the target element.
  • Loading branch information
weltenwort committed Nov 23, 2016
1 parent f80a169 commit 05aedd8
Showing 1 changed file with 51 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/ui/public/multi_transclude/multi_transclude.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import _ from 'lodash';
import angular from 'angular';
import uiModules from 'ui/modules';


const module = uiModules.get('kibana');

module.directive('multiTransclude', function MultiTransclude() {
return {
link: linkMultiTransclude,
restrict: 'A',
scope: {
'multiTransclude': '=',
},
};
});

function linkMultiTransclude(scope, element, attrs, ctrl, transclude) {
const transclusionSlotNames = scope.multiTransclude;
const transcludes = {};

transclude(clone => {
// We expect the transcluded elements to be wrapped in a single div.
const transcludedContentContainer = _.find(clone, item => {
if (item.attributes) {
return _.find(item.attributes, attr => {
return attr.name.indexOf('data-transclude-slots') !== -1;
});
}
});

if (!transcludedContentContainer) {
return;
};

const transcludedContent = transcludedContentContainer.children;
_.forEach(transcludedContent, transcludedItem => {
const transclusionSlot = transcludedItem.getAttribute('data-transclude-slot');
transcludes[transclusionSlot] = transcludedItem;
});
});

// Transclude elements into specified "slots" in the top nav.
transclusionSlotNames.forEach(name => {
const transcludedItem = transcludes[name];
if (transcludedItem) {
const transclusionSlot = document.querySelector(`[data-transclude-slot="${name}"]`);
angular.element(transclusionSlot).append(transcludedItem);
}
});
}

0 comments on commit 05aedd8

Please sign in to comment.