I have a container with two panels as it items. I want both panels to be collapsible (at the same time no one or only one panel can be collapsed) and if any panel is collapsed other panel should take all remaining space. Also I want to be able to resize both panels with Ext.resizer.Splitter.
I have tried different combinations of (h/v)box / border layout, but none of them works correctly.
It seems like Ext.layout.container.Accordion is what I need but, as I can see, it doest work with Ext.resizer.Splitter out of the box.
Also, I want to be able to collapse both panels with single Ext.resizer.Splitter, but as I can see its not available out of the box and I have to override it. Am I right?
I'm using ExtJS version 4.2.1.
Does this help?
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.Container', {
height: 500,
renderTo: Ext.getBody(),
width: 500,
layout: {
type: 'vbox',
align: 'stretch'
},
items: [{
xtype: 'panel',
reference: 'panel1',
title: 'Top panel',
collapsible: true, // To allow collapse
flex: 1,
bodyStyle: 'background: #dadada',
listeners: {
collapse: function(){
this.up().down("[reference='panel2']").expand();
}
}
},
{
xtype: 'splitter'
},
{
xtype: 'panel',
reference: 'panel2',
title: 'Bottom panel',
collapsible: true, // To allow collapse
flex: 1,
bodyStyle: 'background: #999',
listeners: {
collapse: function(){
this.up().down("[reference='panel1']").expand();
}
}
}]
});
}});
Here vbox
is used to set the panels vertically (the flex
property tells them how much space to take from each other). The collapsible
property set to true makes them collapsible. Then each panel has an event that expands the sibling panel when the target panel collapses. With this, at least one panel is always expanded and you can resize them with the splitter!
Edit 1:
The previous code sample isn't generic and does not react as expected if we set panels with animCollapse: false
. A generic solution would look like the following:
// Our extended container
Ext.define('MyVboxContainer', {
extend: 'Ext.Container',
layout: {
type: 'vbox',
align: 'stretch'
},
// We do the setup on initiating the component
initComponent: function () {
var me = this;
var panelCount = 0;
// For each child component
this.items.forEach(function (comp) {
// If the component is a panel
if (comp.xtype === 'panel') {
// We add an unique ref
comp.reference = 'panel' + panelCount;
// Increment the total number of panels
panelCount++
// And listeners for beforecollapse, collapse and expand
comp.listeners = {
// On collpase, we track the last collapsed panel
'collapse': function () {
me.closedCount++;
me.lastClosed = this.reference;
},
// On expand we decrement the total number of panels collapsed
'expand': function () {
me.closedCount--;
},
// If this is the last panel being collapsed,
// we expand the previous collapsed panel
// Note: this cannot be done on the expand event
// if the panel has animCollapse: false
'beforecollapse': function () {
if (me.closedCount + 1 == me.totalPanels) {
me.down("[reference='" + me.lastClosed + "']").expand();
}
}
};
}
});
this.totalPanels = panelCount; // total number of panels
this.lastClosed = null; // Last collapsed panel
this.closedCount = 0; // How many panels we have closed
console.log("Total panels are: " + this.totalPanels)
this.callParent();
}
});
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('MyVboxContainer', {
height: 500,
width: 500,
renderTo: Ext.getBody(),
items: [{
xtype: 'panel',
animCollapse: false,
title: 'Top panel',
collapsible: true, // To allow collapse
flex: 1,
bodyStyle: 'background: #dadada'
}, {
xtype: 'splitter'
}, {
xtype: 'panel',
title: 'Middle panel',
animCollapse: false,
collapsible: true, // To allow collapse
flex: 1,
bodyStyle: 'background: #999'
}, {
xtype: 'splitter'
}, {
xtype: 'panel',
title: 'Bottom panel',
animCollapse: false,
collapsible: true, // To allow collapse
flex: 1,
bodyStyle: 'background: #999'
}]
});
}
});
Here we create an extended container that uses vbox
layout to set the panels vertically. On initComponent
, this container setups the existing children panels to always keep the penultimate collapsed panel expanded. You should modify the algorithm to suit your needs.
Sidenote: it isn't ideal to set variables on the view container. These variables should be moved into a controller.