PDA

View Full Version : Ext.TableContainer A Container class which uses a table as its main element.



Animal
19 Oct 2009, 2:15 AM
To people who dogmatically refuse to use tables to arrange forms, I say PAH!

Sometimes you want rows of input, each of which has more than one input field on.

In fact most forms I've ever written look like that.

With raw Ext, you have to create a Container which uses layout: 'table'. This creates a new table inside the Container's rendered element.

Then in each cell, you have to create a new Container with layout:'form' so that the Fields get rendered with labels.

All of which is a pain, and creates DOM clutter.

This class is a Container who's main element is a table, which is used by its TableLayout instance - no extra DOM layers there.

The cells created by the table layout manager are used as Containers, so no extra layer of DOM required there either.

To use it:



new Ext.FormPanel({
title: 'Tabular input',
layout: 'anchor',
height: 400,
width: 600,
padding: 10,
items: {
xtype: 'tablecontainer',
columns: 2, // Number of columns. Defaults to 1
anchor: '100%',
cellLayout: 'form', // Layout config for each <td>
items: [
{ xtype: 'textfield', fieldLabel: 'Text field 1' },
{ xtype: 'textfield', fieldLabel: 'Text field 2' },
{ xtype: 'datefield', fieldLabel: 'Date field 1' },
{ xtype: 'datefield', fieldLabel: 'Date field 2' },
{ xtype: 'numberfield', fieldLabel: 'Number field 1' },
{ xtype: 'numberfield', fieldLabel: 'Number field 2' }
]
},
renderTo: document.body
});


Which gives you

http://i131.photobucket.com/albums/p286/TimeTrialAnimal/tablecontainerexample.jpg

The class:



Ext.TableContainer = Ext.extend(Ext.Container, (function(){
function getCellSize() {
return { width: this.dom.clientWidth, height: this.dom.clientHeight };
}
return {
firstRowClass: "x-table-layout-first-row",

lastRowClass: "x-table-layout-last-row",

constructor: function(config) {
if (Ext.isObject(config.layout)) {
config.layout.type = 'table'
} else {
config.layout = {
type: 'table'
}
}
config.layout.columns = config.layout.columns || config.columns || 1;
Ext.TableContainer.superclass.constructor.apply(this, arguments);
},

onRender: function() {
Ext.apply(this.layout, {
table: this.el = document.createElement('table'),
renderItem: this.renderItem
});
this.el.id = this.getId();
this.el.appendChild(document.createElement('tbody'));
Ext.TableContainer.superclass.onRender.apply(this, arguments);
},

onResize: function() {
this.el.dom.style.tableLayout = 'fixed';
Ext.TableContainer.superclass.onResize.apply(this, arguments);
},

onLayout: function() {
Ext.TableContainer.superclass.onLayout.apply(this, arguments);
var trs = this.el.select("tr");
trs.removeClass([this.firstRowClass, this.lastRowClass]);
trs.item(0).addClass(this.firstRowClass);
trs.item(trs.getCount() - 1).addClass(this.lastRowClass);
},

renderItem : function(c, position, target){
var w, container, idx, cellEl;
if(c && !c.rendered){
if (Ext.isNumber(w = c.cellWidth)) {
if (w < 1) {
w = (w * 100) + '%'
} else {
w = w + 'px';
}
}
idx = this.container.items.indexOf(c);
this.container.remove(c, false);
cellEl = this.getNextCell(c);
if (w) {
cellEl.style.width = w;
}
cellEl.id = 'ext-comp-' + (++Ext.Component.AUTO_ID);
cellEl = Ext.get(cellEl);
cellEl.getStyleSize = getCellSize;
container = new Ext.Container(Ext.apply({
ownerCt: this.container,
el: cellEl,
id: cellEl.id,
layout: this.container.cellLayout,
items: c
}, c.cellLayout));
Ext.form.FormPanel.prototype.applySettings(container);
this.configureItem(c, position);
this.container.insert(idx, container);
container.render(cellEl.dom.parentNode);
}
}
};
})());
Ext.reg('tablecontainer', Ext.TableContainer);

Bobrovnik
19 Oct 2009, 2:48 AM
great, thanks for sharing

wpoosanguansit
1 Mar 2011, 8:20 AM
Hi,

Thank you for sharing the code. I tried to use the table to do the layout of ExtJS elements and things seem to work fine in Opera, Chrome, Firefox and Safari. However the elements do not show up at all in IE. I tried to narrow it down to the offending code and got it to be something to do with bodyStyle:

var timePane = new Ext.form.FormPanel ({
id: 'time-pane',
bodyStyle: 'border:none; padding: 0% 30% 0% -19%;',
layout: 'form',
items: {
xtype: 'tablecontainer',
columns: 2, // Number of columns. Defaults to 1
anchor: '100%',
cellLayout: 'form', // Layout config for each <td>
items: [
new Ext.form.ComboBox({
store: [
'- Annual Event - External',
'- Annual Event - Internal',
'- Meeting - External',
'- Meeting - Internal'
],
id: 'category',
fieldLabel: 'Category',
typeAhead: true,
mode: 'remote',
triggerAction: 'all',
emptyText:'Select Category..',
selectOnFocus: true,
hideTrigger: false,
width: 410
}),
{
xtype : 'checkbox',
id: 'externally-visible',
fieldLabel : "Externally Visible",
checked: false
}
]
}
});

I do have many similar panes in a big form and I am totally not sure if this is the only issue. Thanks for your help.

jchau
19 Nov 2012, 2:51 PM
Is there a 4.x equivalent? Or does 4.x TableLayout address some of the concerns this fixes?