Sencha Inc. | HTML5 Apps

Layout FAQ

Published Sep 17, 2010 | The Sencha Dev Team | FAQ | Medium
Last Updated Jul 11, 2011

This FAQ is most relevant to Ext JS, any version.

This article is currently due for review
We suspect that this article may be out-of-date or contain incorrect information.
But we are constantly editing articles, so we promise we will get to this one soon.

Layout Size Requirements

  • In order for layouts to work there needs to be 2 things present
  1. a layout which performs sizing on child Components (Not all do) at all levels in the chain and
  2. dimensions at some level in the hierarchy. A layout cannot function correctly if there are no dimensions available which can be used for calculation of the layout.
  • Dimensions can be set in 2 ways.
  1. a size at a top level component that flows down to child components (this is the preferred way) or
  2. a size at a lower component (like the height on a grid) and autoHeight on all parent containers (allowing them to auto adjust to the height of the child grid instead of trying to control the height of the grid).
  • Also note:
    • autoWidth is not supported by a Grid. This means not only for the grid itself, but if it's dimensions are controlled by parent container/layout it also cannot be autoWidth.

Common Mistakes

Common mistakes to check for:

  1. Do all your fieldsets have autoHeight:true (or a fixed height).
  2. Do your tabpanels (or other panel using card layout) that contain layouts have layoutOnTabChange:true'.
  3. items in tabpanel (or other panel using card layout) sometimes require hideMode: 'offsets' to display correctly. hideMode:'offsets' is a config option you need to add to components that contain layouts that are hidden when their container is rendered (hideMode affects the panel that is being hidden/shown so you need to add it to the container that is initially hidden).
  1. layout is missing in your component structure or you have over nested your structure. For example:
{
  layout: 'border',
  items: [{
    region: 'east',
    title: 'Title',
    items: [{
      xtype: 'grid',
      ...
    }]
  }]
}
//The above has an extra panel, which was both unneeded and did
//not have a layout defined, it should be:
{
  layout: 'border',
  items: [{
    region: 'east',
    title: 'Title',
    xtype: 'grid',
    ...
  }]
}

What is difference between contentEl, applyTo and renderTo?

If your page must pull some boilerplate HTML into an Ext Panel, you should be able to use the contentEl config option with a div in your markup with a css class of x-hidden.

  • contentEl - This config option is only for Panels and is used to take an existing HTML element and place it in the body of a new panel (it simply moves the specified DOM element into the body element of the Panel when the Panel is rendered to use... as the content!). It is not going to be the actual panel itself. You should add either the x-hidden or the x-hide-display CSS class to prevent a brief flicker of the content before it is rendered to the panel.

    Note that the HTML element used will not participate in any layout scheme that the Panel may use. It's just HTML. Layouts operate on child items
  • applyTo - This config option allows you to use an existing HTML element as the main, encapsulating element of a Component.

    This is most useful when a Component consists of one simple element.

    If creating a Panel using applyTo, the internal structure required by Panel's capabilities (header, tbar, body, footer, etc) must be already present within the element. See applyTo

    A Component created using applyTo does not need rendering - it's main element already exists.
  • renderTo - renders the Component into the specified existing element.

    Do not use this option if the Component is to be a child item of a Container. It is the responsibility of the Container's layout manager render its child items.

    This config option allows you to render a Component at construction time. This would be the same as saying myPanel.render(ELEMENT_TO_RENDER_TO);

Layout looks wrong in IE but looks ok with others

  • Try removing the doctype definition from the html page entirely.
  • Try hideMode:'offsets'

Component does not show

Call doLayout() on the container after you added all new Components to it.

Adding items

  • To add a new item to a Container, add it using the Container's add() method. You can add several new items at once, without having it redraw the UI each time. Then, when you're done adding, call the Container's doLayout method, and the new item(s) will be rendered.

Adding items to border layout

As per this thread you have 2 options:

  • Option 1
    • Create all possible BorderLayout container regions when you define the UI
    • Add hidden:true for the containers you don't need initially.
    • Create the containers as empty container Panels with baseCls:'x-plain', layout:'fit' and then just use them for adding and removing other Panels. This is probably the better way to do it.
  • Option 2
    • Do as noted above with the container at the top level and then build a new Panel with the layout you need. You can replace the existing one with the new one.

Column Layout

  • Problems with columns, check if this thread sorts you out.

YUI widgets show up beneath other widgets

  • If you are using a feature from YUI like menu, menubars, autocomplete... and it's getting put under my Grid (or other Ext element) it is likely that the z-index of the menu or other element needs to be higher in the YUI CSS.
  • YAHOO! sets z-index very low by default (e.g. 1). Another thing to try is rendering your YUI component to the body element if appropriate. Z-index can only override other elements within the same container. Rendering to the body guarantees that a given element's z-index will always be respected.

Partially Collapse a Panel

//to partially collapse a panel
listeners : {
    beforeCollapse: function(cmp){
        cmp.setHeight(cmp.minHeight);
        cmp.collapsed = true; // needed for the expand button to still work
        return false; // prevents collapsing of the panel.
    }
}

Altering Standard Panel Layout

  • Conceptually, the default structure of a box component is created as so:
<panel>
  <header/>
  <bwrap>
     <tbar/>
     <body/>
     <bbar/>
  </bwrap>
  <footer/>
</panel>
  • For example, toolbars are put into the bwrap which wraps the body. Buttons are in the footer which as you see is below the bbar. Since this is just a plain old HTML document, so you can move things around, perhaps move the bottom toolbar to the footer beneath the buttons:
var metadataForm = new Ext.form.FormPanel({
    renderTo: document.body,
    labelWidth: 75, // label settings here cascade unless overridden
    frame:true,
    title: 'Metadata Details',
    bodyStyle:'padding:5px 5px 0',
    width: 350,
    autoHeight: true,
    defaults: {width: 230},
    defaultType: 'textfield',
    items: [{
            fieldLabel: 'Category',
            name: 'categoryType',
            allowBlank:false
        },{
            fieldLabel: 'Type Id',
            name: 'typeId'
        },{
            fieldLabel: 'Description',
            name: 'description'
        }            
    ],    
    buttons: [{
        text: 'Save'
    },{
        text: 'Cancel'
    }],
    bbar: [{ text: 'Button'}],
    listeners: {
        render: function(p) {
            p.footer.dom.appendChild(p.getBottomToolbar().el.dom);
        }
    }
});

Sample Layout (anchor)

+-------------------------------+
|+-----------------------------+|
||+------------++-------------+||
|||            ||             |||
|||            ||             |||
||+------------++-------------+||
|+-----------------------------+|
|+-----------------------------+|
||                             ||
||                             ||
||                             ||
|+-----------------------------+|
+-------------------------------+
  • the outer Panel is layout: 'anchor'. It contains 2 child items.
    • The first child item is layout:'column', anchor:'100%'.
      • It contains two Panels as the two columns sized as you wish - see the ColumnLayout API docs.
    • The second child item is anchor: '100%'

Reference a viewport region

var vp = new Ext.Viewport({
    layout: 'border',
    items: [{
        region: 'center',
        border: false
    }]
});
 
var region = vp.layout.center.panel;

Panel vs Container

  • If you don't explicitly state the xtype, usually a Panel is created as the defaultType. Ext.Panel is a heavyweight class which offers borders, header, header tools, footer, toolbars etc.
  • Unless you need borders, header, footer, buttons etc. do not create a Panel.
  • If all you are doing is containing things, just use a simple Container:
{
    xtype: 'container',
    autoEl: {},  // DomHelper spec. Tag defaults to 'div'
    layout: 'column',// whatever layout YOU want
    items: [{
        xtype: 'container',
        autoEl: {},
        columnWidth: 0.5,
        layout: 'form'
        ....
  • The above code creates a pure Ext.Container from a DIV and has the ability to manage child Components using a layout, and that is all.
  • A Container (like FormPanel, TabPanel, GridPanel are all Containers, see the inheritance chain at the top of every page of the API docs) can contain any Components. They must be BoxComponents if they are going to be sized by the Contrainer's layout though. So, if you just need to poke in some html into a container you can simply create a Component which encapsulates HTML:
{
    xtype: 'component',
    autoEl: {
        tag: 'div', // Or whatever your outer tag is!
        html: 'The HTML code to go inside it'
    }
}

Accordion (Multiple items open at same time)

Toolbar centering

  • Centering the toolbar elements:
    • Option 1:
myToolbar.getEl().child("table").wrap({tag:'center'})
    • Option 2:
var t = myGridPanel.getBottomToolbar().el;
var c = t.createChild("<center></center>");
c.appendChild(t.child("table"));

Multiple toolbars

Wrapping toolbars

  • Scalable/wrapping Toolbar for when toolbar needs to wrap see this thread
Share this post:
Leave a reply

Written by The Sencha Dev Team

Commenting is not available in this channel entry.