Dynamically adding Components
Often you'd want to give your users the ability to add new items to an existing layout. GoldenLayout offers a number of ways to do this.
- You can turn any DOM element on the page into a 'dragSource' that turns into a layoutItem when dragged
- You can let the user select an element and add items to it
- You can add items to a specified element
Creating a layout
For this tutorial we won't insert the layout directly into the body, but rather into a div to leave some space for a component menu.
<div id="wrapper">
<ul id="menuContainer"></ul>
<div id="layoutContainer"></div>
</div>
Let's keep things simple: Create a basic layout with two components in a row
var config = {
content: [{
type: 'row',
content: [{
type:'component',
componentName: 'example',
componentState: { text: 'Component 1' }
},
{
type:'component',
componentName: 'example',
componentState: { text: 'Component 2' }
}]
}]
};
var myLayout = new window.GoldenLayout( config, $('#layoutContainer') );
myLayout.registerComponent( 'example', function( container, state ){
container.getElement().html( '<h2>' + state.text + '</h2>');
});
myLayout.init();
Creating the "insert component" menu
The "insert component" menu will be created programmatically as well. That's where we'll add the actual insertion code later on
var addMenuItem = function( text ) {
var element = $( '<li>' + text + '</li>' );
$( '#menuContainer' ).append( element );
//insertion code will go here
};
addMenuItem( 'User added component A' );
addMenuItem( 'User added component B' );
Adding items to a layout - in general
Time to write some "add component" functionality. GoldenLayout builds up a tree of items internally that can be accessed through 'myLayout.root' once the layout is initialised. Every one of these items has an addChild
method that expects two parameters: itemOrConfig
and index
.
Nevermind index
for now. It's optional and specifies at which position the new child will be added. The important bit for us is itemOrConfig
. This can be any kind of item config - which means it's also possible to create / insert a whole tree of new items at once.
Let's prepare a bit of item configuration in our 'addMenuItem' function
var newItemConfig = {
type: 'component',
componentName: 'example',
componentState: { text: text }
};
The tricky bit is not so much creating the item, but selecting the element to which to add the item to. All three approaches we'll cover next are basically just that: different ways of selecting the parent for the new item.
First: The really awesome way
GoldenLayout makes it simple to turn any DOM element into a "dragSource" - which allows for the creation of components by simply dragging the element onto the layout.
All that needs adding to our 'addMenuItem' method is this line:
myLayout.createDragSource( element, newItemConfig );
Works like a charm:
See the Pen Adding items from drag Sources by Wolfram Hempel (@wolframhempel) on CodePen.
Second: Add items to a selected stack
GoldenLayout supports selecting items by clicking the empty space in the header area. This is however disabled by default. To enable it, simply add this to your config:
var config = {
settings: {
selectionEnabled: true
},
content: [...]
};
Now if the user clicks a header it turns into a different color, GoldenLayout emits a 'selectionChanged' event and the value of 'myLayout.selectedItem' points to the selected item.
To use this we'll change our insert logic to this:
element.click(function(){
if( myLayout.selectedItem === null ) {
alert( 'No item selected' );
} else {
myLayout.selectedItem.addChild( newItemConfig );
}
});
Now clicking a li in the "insert component" menu will add the component to whatever stack is selected - or alert if no selection has been made.
See the Pen Adding items to selected stacks by Wolfram Hempel (@wolframhempel) on CodePen.
Third: Adding items to a previously specified element
If we don't want to give the user a choice of where to add the new item, we can just specify an element ourselves. Either by using one of the getter-functions, (e.g. myLayout.root.getItemsById( 'someItem' );
) or by traversing the item tree.
For instance, if we always want to add items to the topmost row, it would look like this:
element.click(function(){
myLayout.root.contentItems[ 0 ].addChild( newItemConfig );
});
See the Pen Adding items to a predefined parent by Wolfram Hempel (@wolframhempel) on CodePen.