- Ext JS 3.0 Cookbook
- Jorge Ramon
- 1359字
- 2021-04-01 13:43:49
A three-panel application layout with a single line of code
This recipe explains how you can build a reusable Ext JS component that encapsulates one of the most popular GUI styles—a three-panel layout. Using the component will produce a layout like the one shown in the following screenshot:

This layout consists of a Navigation panel, a Master panel, and a Details panel as shown in the following screenshot:

The Master panel has a toolbar with a button that switches the Details panel's location from bottom to right, or hides it altogether:

Besides being able to add components to any of the layout's panels via configuration objects, you can also reconfigure any of the panels by the same means.
How to do it...
- Create the skeleton code of our component:
Ext.ns('Ext.ux'); Ext.ux.ThreePanelApp=function(conf) { // Master Panel // Details Panel // Nav Panel // MasterDetailsCnt }
- Create the Master panel:
MasterPanel=function(conf) { config={ title: 'Master', region: 'center', tbar: [{ split: true, text: 'Details Panel', id: 'details-panel-button', handler: this.toggleDetails.createDelegate(this, []), menu: { id: 'details-menu', cls: 'details-menu', width: 100, items: [{ text: 'Bottom', checked: true, group: 'rp-group', checkHandler: this.toggleDetails, scope: this, iconCls: 'details-bottom' }, { text: 'Right', checked: false, group: 'rp-group', checkHandler: this.toggleDetails, scope: this, iconCls: 'details-right' }, { text: 'Hide', checked: false, group: 'rp-group', checkHandler: this.toggleDetails, scope: this, iconCls: 'details-hide' }] } }] }; Ext.apply(config, conf || {}); MasterPanel.superclass.constructor.call(this, config); }
- Specify that the Master panel extends the
Ext.Panel
class and implements thetoggleDetails()
function:Ext.extend(MasterPanel, Ext.Panel, { toggleDetails: function(m, pressed) { if (!m) { var readMenu=Ext.menu.MenuMgr.get('details-menu'); readMenu.render(); var items=readMenu.items.items; var b=items[0], r=items[1], h=items[2]; if (b.checked) { r.setChecked(true); } else if (r.checked) { h.setChecked(true); } else if (h.checked) { b.setChecked(true); } return; } if (pressed) { var details=Ext.getCmp('details-panel'); var right=Ext.getCmp('right-details'); var bot=Ext.getCmp('bottom-details'); switch (m.text) { case 'Bottom': right.hide(); right.remove(details, false); bot.add(details); bot.show(); bot.ownerCt.doLayout(); break; case 'Right': bot.hide(); bot.remove(details, false); right.add(details); right.show(); right.ownerCt.doLayout(); break; case 'Hide': bot.hide(); right.hide(); right.remove(details, false); bot.remove(details, false); right.ownerCt.doLayout(); break; } } } });
- Check if a configuration object for the Master panel was specified and create the Master panel instance:
var masterPanelConf={}; if (conf && conf.masterPanelConf) { masterPanelConf=conf.masterPanelConf; } var masterPanel=new MasterPanel(masterPanelConf);
- Similar to the Master panel, create the Details panel:
DetailsPanel=function(conf) { config={ id: 'details-panel', layout: 'fit', title: 'Details', id: 'details-panel' }; Ext.apply(config, conf || {}); DetailsPanel.superclass.constructor.call(this, config); } Ext.extend(DetailsPanel, Ext.Panel); var detailsPanelConf={}; if (conf && conf.detailsPanelConf) { detailsPanelConf=conf.detailsPanelConf; } var detailsPanel=new DetailsPanel(detailsPanelConf);
- Repeat the process with the Navigation panel:
NavPanel=function(conf) { config={ title: 'Navigation', region: 'west', margins: '5 0 5 5', cmargins: '5 5 5 5', width: 200, minSize: 100, maxSize: 300 }; Ext.apply(config, conf || {}); NavPanel.superclass.constructor.call(this, config); } Ext.extend(NavPanel, Ext.Panel); var navPanelConf={}; if (conf && conf.navPanelConf) { navPanelConf=conf.navPanelConf; } var navPanel=new NavPanel(navPanelConf);
- Define a container for the Master and Details panels:
MasterDetailsCnt=function(conf) { config={ layout: 'border', region: 'center', collapsible: false, border: false, margins: '5 5 5 0', id: 'main-view', hideMode: 'offsets', items: [masterPanel , { id: 'bottom-details', layout: 'fit', height: 300, split: true, border: false, region: 'south', items: detailsPanel }, { id: 'right-details', layout: 'fit', border: false, region: 'east', width: 350, split: true, hidden: true }] }; Ext.apply(config, conf || {}); MasterDetailsCnt.superclass.constructor.call(this, config); }
- Check if a configuration object for the Master/Details container panel was specified, and create the object's instance:
Ext.extend(MasterDetailsCnt, Ext.Panel); var masterDetailsCntConfig={}; if (conf && conf.masterDetailsCntConfig) { masterDetailsCntConfig=conf.masterDetailsCntConfig; } var masterDetailsCnt=new MasterDetailsCnt(masterDetailsCntConfig);
- Now that the panels have been created, define the layout:
Ext.ux.ThreePanelApp=function(conf) { // Master Panel // Details Panel // Nav Panel // MasterDetailsCnt config={ layout: 'border', defaults: { collapsible: true, split: true }, items: [{ xtype: 'box', el: 'app-header', height: 40, region: 'north' }, navPanel, masterDetailsCnt] }; if (conf) { Ext.apply(config, conf); } Ext.ux.ThreePanelApp.superclass.constructor.call(this, config); } Ext.extend(Ext.ux.ThreePanelApp, Ext.Viewport)
- Your custom layout is ready to be used and you can create it with only one line of code:
Ext.onReady(function() { var container=new Ext.ux.ThreePanelApp(); });
- Add a tree view to the Navigation panel and change the panels' titles:
Ext.onReady(function() { var navPanel={ title: 'MyInbox', collapsible: true, layout: 'fit', items: { xtype: 'treepanel', id: 'inbox-tree', autoScroll: true, animate: true, enableDD: true, containerScroll: true, border: false, dataUrl: 'mail-folders.php', root: { nodeType: 'async', text: 'MailBox', draggable: false, id: 'mailbox' } } } var detailsPanel={ title: 'Re: Join us for happy hour' } var masterPanel={ title: 'Messages List' } var container=new Ext.ux.ThreePanelApp({ detailsPanelConf: detailsPanel, navPanelConf: navPanel, masterPanelConf: masterPanel }); });
In the following screenshot, you will see what the finished layout looks like:

How it works...
The ThreePanelApp
layout is essentially a custom Ext JS component based on the Ext.Viewport
class. Creating the layout starts with a basic code template. This template has placeholders for each of the panels in the layout.
Ext.ns('Ext.ux'); Ext.ux.ThreePanelApp=function(conf) { // Master panel // Details panel // Nav panel // MasterDetailsCnt panel }
Notice that in addition to the placeholders for the Navigation, Master, and Details panels, there is a place for a fourth panel—MasterDetailsCnt
. This panel will be a container for the Master panel and two additional panels that will host the Details panel when it is positioned below or to the right of the Master panel respectively. ThreePanelApp
will use a border layout that will contain the Navigation panel (which will take the west region) and the MasterDetailsCnt
panel (which will take the center region). MasterDetailsCnt
will use a BorderLayout
to position the Master and Details panels' hosts.
Moving on, the Master panel is an Ext.Panel
extension that contains the cycle
button for repositioning the Details panel:
tbar: [{ handler: this.toggleDetails.createDelegate(this, []), }]
The Master Panel uses a default config
object that gets overridden by the masterPanelConf
object passed during the construction of a ThreePanelApp
instance:
MasterPanel=function(conf) { Ext.apply(config, conf || {}); MasterPanel.superclass.constructor.call(this, config); }
This pattern of overriding the default configuration (also used with the rest of the panels), allows you to add your application's components to ThreePanelApp
.
Another interesting area in the Master panel is the toggleDetails()
function. This function achieves the repositioning of the Details panel by switching the panel's container or hiding it altogether as shown here:
toggleDetails: function(m, pressed) { var details=Ext.getCmp('details-panel'); var right=Ext.getCmp('right-details'); var bot=Ext.getCmp('bottom-details'); switch (m.text) { case 'Bottom': right.hide(); right.remove(details, false); bot.add(details); bot.show(); bot.ownerCt.doLayout(); break; case 'Right': bot.hide(); bot.remove(details, false); right.add(details); right.show(); right.ownerCt.doLayout(); break; case 'Hide': bot.hide(); right.hide(); right.remove(details, false); bot.remove(details, false); right.ownerCt.doLayout(); break; } }
After defining the Master panel, the layout creates a working instance of this panel and applies any supplied configuration for it.
var masterPanelConf={}; if (conf && conf.masterPanelConf) { masterPanelConf=conf.masterPanelConf; } var masterPanel=new MasterPanel
The Details and Navigation panels do not have any out-of-the-box extra functionality and hence their creation is less involved. As with the Master panel, you can add components to these panels when building the layout by overriding their default configurations.
MasterDetailsCnt
is a container panel for the Master and Details panels hosts. Notice how one host uses the south
region of the MasterDetailsCnt
layout, whereas the other uses the east
region:
MasterDetailsCnt=function(conf) { config={ items: [ masterPanel, { id: 'bottom-details', layout: 'fit', height: 300, split: true, border: false, region: 'south', items: detailsPanel }, { id: 'right-details', layout: 'fit', border: false, region: 'east', width: 350, split: true, hidden: true }] } }
When all of the panels needed by the ThreePanelApp
component are created, what's left is defining the custom layout for the component. Notice the inclusion of a north
region where you can put a logo and other components:
Ext.ux.ThreePanelApp=function(conf) { config={ layout: 'border', defaults: { collapsible: true, split: true }, items: [{ xtype: 'box', el: 'app-header', height: 40, region: 'north' }, navPanel, masterDetailsCnt] }; if (conf) { Ext.apply(config, conf); } Ext.ux.ThreePanelApp.superclass.constructor.call(this, config); }
Now the custom layout can be put into action:
var navPanel={ ... } var detailsPanel={ ... } var masterPanel={ ... } var container=new Ext.ux.ThreePanelApp({ detailsPanelConf: detailsPanel, navPanelConf: navPanel, masterPanelConf: masterPanel });
There's more...
Use this layout when you need a simple three-panel GUI without having to worry about all its plumbing. More importantly, the extension model used in ThreePanelApp
can be used as a reference for creating even more complex reusable layouts and custom components.
See also...
- The recipe, Creating a modern application layout with collapsible region (seen earlier in this chapter), explains how to create one of the most popular UI layouts
- Vulkan學習指南
- Creo 4.0中文版從入門到精通
- Microsoft Visual C++ Windows Applications by Example
- Adobe 創意大學動漫設計師Flash CS5 + Photoshop CS5 標準實訓教材
- 中文版CorelDRAW基礎培訓教程
- Puppet 2.7 Cookbook
- Illustrator平面設計立體化教程:Illustrator 2021(微課版)
- 零基礎學數碼攝影后期
- 從零開始:AutoCAD 2010中文版建筑制圖基礎培訓教程(第2版)
- Microsoft Azure: Enterprise Application Development
- SharePoint Designer Tutorial: Working with SharePoint Websites
- NX Open API編程技術
- Scribus 1.3.5: Beginner's Guide
- 中文版Corel DRAW X5案例實訓教材
- 中文版Illustrator CC完全自學教程