PDA

View Full Version : Ext.ux.layout.TableFormLayout



mbajema
23 Jun 2008, 6:48 AM
I've seen a number of posts by users wishing field labels rendered in the table layout (they do in the column layout for example). A common response is to wrap each field with a container/panel with the form layout. This does work, but requires a lot of nested containers.

I created a very simple table-form layout which automatically wraps each item with an Ext.Panel with a form layout so that field labels are rendered as well (for some reason I couldn't get this to work with an Ext.Container):

Source:

Ext.namespace('Ext.ux.layout');
Ext.ux.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout,
{
renderAll : function(ct, target)
{
var items = ct.items.items;
for (var i = 0, len = items.length; i < len; i++)
{
var c = items[0]; // use 0 index because the array shrinks by one after each call to renderItem()
if (c && (!c.rendered || !this.isValidParent(c, target)))
{
this.renderItem(c, i, target);
}
}
},

renderItem : function(c, position, target){
if (c && !c.rendered)
{
var td = this.getNextCell(c);
var p = new Ext.Panel(Ext.apply(this.container.formConfig,
{
layout: 'form', // this is the tableform layout so force each cell panel to have a form layout
items: c,
renderTo: td
}));
}
}
});
Ext.Container.LAYOUTS['tableform'] = Ext.ux.layout.TableFormLayout;Sample:

Ext.onReady(function()
{
Ext.QuickTips.init();

var p = new Ext.Panel(
{
layout: 'tableform',
title: 'Table-Form Layout',
bodyStyle: 'padding:6px',
renderTo: Ext.getBody(),
layoutConfig: {columns:3},
formConfig: // config options to be applied to each panel in each table cell
{
layoutConfig:
{
labelSeparator: ''
},
bodyStyle: 'padding:0 3px',
labelAlign: 'top',
border: false
},
items:
[
{
xtype: 'textfield',
fieldLabel: 'Field 1',
name: 'Field1',
width: 115
},
{
xtype: 'textfield',
fieldLabel: 'Field 2',
name: 'Field2',
width: 115
},
{
xtype: 'textfield',
fieldLabel: 'Field 3',
name: 'Field3',
width: 115
},
{
xtype: 'textfield',
fieldLabel: 'Field 4',
name: 'Field4',
width: 115
},
{
colspan: 2,
xtype: 'textfield',
fieldLabel: 'Field 5',
name: 'Field5',
width: 236
}
]
});
});Demo:
http://www.innovativetechsolutions.net/kb/extjs/examples/layout/tableform.htm

mdissel
23 Jun 2008, 10:23 AM
Very nice! it fixes two "errors":
- tab order
- anchoring when using multiple columns (and col spanning)

mdissel
23 Jun 2008, 10:40 AM
One issue when using anchoring.. The size of the fields is not correct when i changed your sample using this config:


layoutConfig: {columns:3},
formConfig: // config options to be applied to each panel in each table cell
{
layoutConfig:
{
labelSeparator: '',
anchor: '88%'
},
defaults:{
msgTarget: 'side'
},
bodyStyle: 'padding:0px 3px',
labelAlign: 'top',
border: false
},

debarcar
30 Jun 2008, 2:51 AM
It is great extension!

In my environment, it is ok for ext 2.0 library...but when I switch to 2.1 library, it show:

A.container has no properties
chrome://firebug/content/blank.gifExt.FormPanel=Ext.extend(Ext.Panel,{buttonAlign:"center",minButtonWidth:75,label...

Could you please to tell me how to fix this?

Animal
30 Jun 2008, 4:45 AM
Bit heavyweight to use a Panel as the inner Container. You don't need all the machinery of Panel, it's only a Container, and you can use the existing <td> as the element for it, so no need for any deep DOM nesting...:

try this, and let us know how it goes:



renderItem : function(c, position, target) {
if (c && !c.rendered) {
var td = this.getNextCell(c)
new Ext.Container(Ext.apply(this.container.formConfig, {
el: td,
renderTo: td.parentNode,
layout: 'form', // this is the tableform layout so force each cell to have a form layout
items: c
}));
}
}

Animal
30 Jun 2008, 6:10 AM
OK, how about this version?



<html>
<head>
<title>Absolute Forms</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css"/>

<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->

<script type="text/javascript" src="../../ext-all-debug.js"></script>

<link rel="stylesheet" type="text/css" href="forms.css"/>

<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="../examples.css"/>
</head>
<script type="text/javascript">

Ext.override(Ext.layout.FormLayout, {
fieldTpl: (function() {
var t = new Ext.Template(
'<div class="x-form-item {5}" tabIndex="-1">',
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
'</div><div class="{6}"></div>',
'</div>'
);
t.disableFormats = true;
return t.compile();
})()
});

Ext.namespace('Ext.ux.layout');
Ext.ux.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
fieldTpl: Ext.layout.FormLayout.prototype.fieldTpl,

renderItem : function(c, position, target) {
if (c && !c.rendered) {
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
}
}
});
Ext.Container.LAYOUTS['tableform'] = Ext.ux.layout.TableFormLayout;

Ext.onReady(function()
{
Ext.QuickTips.init();

var p = new Ext.Panel(
{
layout: 'tableform',
title: 'Table-Form Layout',
bodyStyle: 'padding:6px',
renderTo: Ext.getBody(),
layoutConfig: {columns:3},
formConfig: // config options to be applied to each panel in each table cell
{
layoutConfig:
{
labelSeparator: ''
},
bodyStyle: 'padding:0 3px',
labelAlign: 'top',
border: false
},
items:
[
{
xtype: 'textfield',
fieldLabel: 'Field 1',
name: 'Field1',
width: 115
},
{
xtype: 'textfield',
fieldLabel: 'Field 2',
name: 'Field2',
width: 115
},
{
xtype: 'textfield',
fieldLabel: 'Field 3',
name: 'Field3',
width: 115
},
{
xtype: 'textfield',
fieldLabel: 'Field 4',
name: 'Field4',
width: 115
},
{
colspan: 2,
xtype: 'textfield',
fieldLabel: 'Field 5',
name: 'Field5',
width: 236
}
]
});
});
</script>
<body>
</body>
</html>

mdissel
30 Jun 2008, 7:17 AM
What's the reason of the override of Ext.layout.FormLayout.fieldTpl?

Animal
30 Jun 2008, 8:00 AM
Because Ext.layout.FormLayout.prototype.renderItem uses this.fieldTpl which is only available in Ext.layout.FormLayout - and then, only after it has been invoked once - hence the override to ensure its always there in the prototype.

durlabh
30 Jun 2008, 11:39 AM
I think we need to update the setContainer method also for tableform layout to be able to use properties such as labelWidth etc.


/**
* Needed for tableform layout
**/
Ext.override(Ext.layout.FormLayout, {
fieldTpl: (function() {
var t = new Ext.Template(
'<div class="x-form-item {5}" tabIndex="-1">',
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
'</div><div class="{6}"></div>',
'</div>'
);
t.disableFormats = true;
return t.compile();
})()
});

/**
* Table form layout
**/
Ext.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
setContainer : function(ct){
Ext.layout.TableFormLayout.superclass.setContainer.call(this, ct);
if(ct.labelAlign){
ct.addClass('x-form-label-'+ct.labelAlign);
}

if(ct.hideLabels){
this.labelStyle = "display:none";
this.elementStyle = "padding-left:0;";
this.labelAdjust = 0;
}else{
this.labelSeparator = ct.labelSeparator || this.labelSeparator;
ct.labelWidth = ct.labelWidth || 100;
if(typeof ct.labelWidth == 'number'){
var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
this.labelAdjust = ct.labelWidth+pad;
this.labelStyle = "width:"+ct.labelWidth+"px;";
this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
}
if(ct.labelAlign == 'top'){
this.labelStyle = "width:auto;";
this.labelAdjust = 0;
this.elementStyle = "padding-left:0;";
}
}
},

fieldTpl: Ext.layout.FormLayout.prototype.fieldTpl,

renderItem : function(c, position, target) {
if (c && !c.rendered) {
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
}
}
});
Ext.Container.LAYOUTS['tableform'] = Ext.layout.TableFormLayout;

mbajema
30 Jun 2008, 1:36 PM
Animal,

Thanks for posting an alternative solution. However, I'm not sure how to make it work with labels on top. Ultimately, I'm not sure why Ext JS doesn't render labels with form fields in all layouts, but it is probably because it is relatively complex to handle all of the options for labels.

In the forums, the response to attempting to use form fields in a table layout is always that you have to put an extra layer of containers specifying the "form" layout in each one and then putting the form fields in those containers. My approach was to just automate this so that each table/form didn't need so many nested containers in the code. I'm not sure why I had to make it a Panel, but my approach didn't work with the generic Container object.

I would be interested in using a robust table/form layout if it is workable. Can you expand your solution to work with the various label options?

durlabh
30 Jun 2008, 2:09 PM
Have you tried with the setContainer change I made? That works with different labelAlign options as well. You can assign labelWidth etc. as well as you would set on a form.

So, your config can be something like



{
layout: 'tableform',
layoutConfig: {columns: 2},
border: 'false',
labelWidth: 200,
labelAlign: 'top',
items: [
{xtype: 'textbox', fieldLabel: 'First Name'},
{xtype: 'textbox', fieldLabel: 'Last Name'},
{xtype: 'textarea', fieldLabel: 'Remarks', colspan: 2}
]
}


Let me know what kind of issues you are encountering!

Animal
30 Jun 2008, 11:41 PM
Yes, durlabh's solution will fix the OP's problem. It looks like the way to go.

I've posted a Feature Request that this be added to the main Ext codebase. I think that 99% of form layouts are tabular.

The vertical, linear nature of Ext.layout.FormLayout baffles first time Ext users.

Animal
30 Jun 2008, 11:44 PM
I think this should have the effect we are after:



// Make the fieldTpl available to ALL layouts
Ext.override(Ext.layout.ContainerLayout, {
fieldTpl: (function() {
var t = new Ext.Template(
'<div class="x-form-item {5}" tabIndex="-1">',
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
'</div><div class="{6}"></div>',
'</div>'
);
t.disableFormats = true;
return t.compile();
})()
});


And the new layout class:



Ext.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
setContainer: function() {
Ext.layout.FormLayout.prototype.setContainer.apply(this, arguments);
this.currentRow = 0;
this.currentColumn = 0;
this.cells = [];
},

renderItem : function(c, position, target) {
if (c && !c.rendered) {
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
}
}
});
Ext.Container.LAYOUTS['tableform'] = Ext.layout.TableFormLayout;

mystix
1 Jul 2008, 12:01 AM
animal, with your override from post #13 i get this error (on 2.1svn):

http://img360.imageshack.us/img360/3289/200807011600zt8.png

p.s. anyway to get anchors working with this?

mabello
1 Jul 2008, 12:05 AM
Good tip, I have not tried the code though, but I will.
I'm wondering if the new layout need a destroy override...
The benefit of making the fieldTpl available to all layouts is because then you can use it to render fields in all the layouts...but it works only if you use the renderItem of the form layout for now...
Am I correct?

Thanks and keep up the good work

mdissel
1 Jul 2008, 12:19 AM
Yes, durlabh's solution will fix the OP's problem. It looks like the way to go.

I've posted a Feature Request that this be added to the main Ext codebase. I think that 99% of form layouts are tabular.

The vertical, linear nature of Ext.layout.FormLayout baffles first time Ext users.

100% agreed!!

Animal
1 Jul 2008, 12:24 AM
Mystix, I just fixed the code in the post #13.

mystix
1 Jul 2008, 12:29 AM
Mystix, I just fixed the code in the post #13.

sweet. works great now :)

would you recommend a bodyStyle config to handle the lack of padding, or a form-like anchor config (which currently isn't applicable for this plugin)?

[edit]
scratch that, there's no bodyStyle config for cells.
guess writing css's the way to go.

Animal
1 Jul 2008, 1:27 AM
The TableLayout class has the cellCls config. But I would like it to also have cellStyle.

And in the layoutConfig, tableCls and tableStyle.

I usually need to add style="width:100%" to my table layouts.

Animal
1 Jul 2008, 1:29 AM
Actually, there is tableAttrs in SVN. I'll comment it so that we can see it.

mystix
1 Jul 2008, 2:37 AM
=D> whoopee!

mdissel
1 Jul 2008, 9:48 AM
Actually, there is tableAttrs in SVN. I'll comment it so that we can see it.

Yes, but not in the 2.1 version... :-?

Are you already working with the 3.0 version?

Animal
2 Jul 2008, 1:07 AM
Yes. Aren't you?

mystix
2 Jul 2008, 1:41 AM
Yes. Aren't you?

errr, nope. :">

no time to dig in just yet...

mdissel
3 Jul 2008, 1:27 AM
Yes. Aren't you?

No not yet, are you using ext 3 in production?

Animal
3 Jul 2008, 10:23 AM
Well, our app is a long way off release. It's not going to be seen by anyone until well after Ext 3.<mumble> is out there in common usage!

I get to test new features, and if I find a bug, I add an override, and post a report.

radustefan
4 Jul 2008, 3:20 PM
Which is the last version of this extension?

The one that uses Panel or the one that uses Templates?

I want to embed in the cells some FieldSets, how do I align them at top?

rissato
9 Jul 2008, 9:09 AM
Hello everybody,

first of all, this is a very nice layout. It will save me several Label declarations :D. Now here goes my question:

Is there a way to define a labelWidth or labelAlign for just one specific cell?

For example, I need only one textfield to have the labelWidth to a diferent value.

radustefan
9 Jul 2008, 1:00 PM
Please if anyone has an idea about fieldsets alignment inside tableform.
I want to align them to TOP.

durlabh
9 Jul 2008, 1:39 PM
Have you tried the config labelAlign: 'top' for the tableform?

radustefan
9 Jul 2008, 3:41 PM
That's for labels, I want the whole groupbox aligned to top. I tried to use style: 'vertical-align:top' but my FieldSet is autoHeight: true and it doesn't work.

Animal
10 Jul 2008, 12:47 AM
I don't understand what you mean. "the whole groupbox"?

mystix
10 Jul 2008, 4:33 AM
i think he wants the top of the "detail" fieldset aligned with the top of the "address" fieldset...

Animal
10 Jul 2008, 4:49 AM
Ah, so it's the fieldsets that are layed out in the TableFormLayout.

Should just use TableLayout then, no need for field rendering abailities!

But still, the TD would be high enough to contain the taller fieldset, and TDs are have valign="middle" by default: http://www.w3.org/TR/REC-html40/struct/tables.html#adef-align-TD

If you style the layout's cells vertical-align: top it should work.



.my-form-class td.x-table-layout-cell {
vertical-align: top;
}

radustefan
14 Jul 2008, 2:56 PM
Thank you, the top alignment works now.

I am using TabPanel with Panels with tableform layout. You really need to set layoutOnTabChange: 'true' to your tabPanel config, as I found in another post.
Maybe someone will search for this issue.

wuschba
16 Jul 2008, 4:38 AM
Thanks a lot!

How would you set relative widths to the input-fields? In a FormLayout you can use:
defaults: { anchor: '50%' }
but since TableLayout is not a AnchorLayout this won't work. I tried and it seems you could use
defaults: { width: '50%' }
but I the API says that width only should be a number. So how is it done?

Animal
16 Jul 2008, 4:44 AM
It won't handle that, someone has to go in and update TableFormLayout to contain the anchor processing code from AnchorLayout and I don't have the time.

skaue
9 Oct 2008, 3:54 AM
So what is the most recent version of TableFormLayout? Is the one that Animal, or the one in the original post? :)

long_geng
9 Oct 2008, 7:35 AM
Add the last 3 functions(OnLayout, adjustWidthAnchor , adjustHeightAnchor ) to Tableformlayout. Then It 's OK for Anchor.


// Make the fieldTpl available to ALL layouts
Ext.override(Ext.layout.ContainerLayout, {
fieldTpl: (function() {
var t = new Ext.Template(
'<div class="x-form-item {5}" tabIndex="-1">',
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
'</div><div class="{6}"></div>',
'</div>'
);
t.disableFormats = true;
return t.compile();
})()
});

Ext.layout.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
setContainer: function() {
Ext.layout.FormLayout.prototype.setContainer.apply(this, arguments);
this.currentRow = 0;
this.currentColumn = 0;
this.cells = [];
},


onLayout : function(ct, target){
Ext.layout.TableFormLayout.superclass.onLayout.call(this, ct, target);

var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
// find the container anchoring size
var aw, ah;
for(i = 0; i < len; i++){
c = cs[i];
var td=Ext.get(c.getEl().parent());
aw=td.getWidth();
ah=td.getHeight();
var w = aw, h = ah;

if(c.anchor){
a = c.anchorSpec;
if(!a){ // cache all anchor values
var vs = c.anchor.split(' ');
c.anchorSpec = a = {
right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
};
}
cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;

if(cw || ch){
c.setSize(cw || undefined, ch || undefined);
}
}
}
},

renderItem : function(c, position, target) {
if (c && !c.rendered) {

Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));

}
},


// private
parseAnchor : function(a, start, cstart){
if(a && a != 'none'){
var last;
if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor
var diff = cstart - start;
return function(v){
if(v !== last){
last = v;
return v - diff;
}
}
}else if(a.indexOf('%') != -1){
var ratio = parseFloat(a.replace('%', ''))*.01; // percentage
return function(v){
if(v !== last){
last = v;
return Math.floor(v*ratio);
}
}
}else{
a = parseInt(a, 10);
if(!isNaN(a)){ // simple offset adjustment
return function(v){
if(v !== last){
last = v;
return v + a;
}
}
}
}
}
return false;
},

// private
adjustWidthAnchor : function(value, comp){
return value - (comp.isFormField ? (comp.hideLabel ? 0 : this.labelAdjust) : 0); },

// private
adjustHeightAnchor : function(value, comp){
return value;
}
});
Ext.Container.LAYOUTS['tableform'] = Ext.layout.TableFormLayout;

///////////////////////////////////////////////////////////////////////////////////

Sample:
[code]
/*
* TableForm
*/
TableForm = function(cfg) {
config={
layout: 'tableform',
title: cfg["title"],
bodyStyle: 'padding:0px',
// config options to be applied to each panel in each table cell
layoutConfig:
{
labelSeparator: ':'
},
bodyStyle: 'padding:3 3px',
labelAlign: 'right',
//labelWidth: 70,
labelPad: 20,
border: false,
fileUpload: true,
layoutConfig: {
columns:cfg["columns"],
labelSeparator: ':'
},
tbar:[
{
id:'btnSave',
text:'

dinosauro
27 Oct 2008, 6:48 AM
Could you post a small complete example with .js and .html files ?

Tanks

JamesC
9 Nov 2008, 12:52 PM
I couldn't get long_geng's example to work properly, however it did spark me to add to this plugin. Here it is with anchoring support, and it works very well for what I want it for!



Ext.namespace("Ext.ux");

Ext.override(Ext.layout.ContainerLayout, {
fieldTpl: (function() {
var t = new Ext.Template(
'<div class="x-form-item {5}" tabIndex="-1">',
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
'</div><div class="{6}"></div>',
'</div>'
);
t.disableFormats = true;
return t.compile();
})()
});

Ext.ux.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
monitorResize:true,
setContainer: function() {
Ext.layout.FormLayout.prototype.setContainer.apply(this, arguments);
this.currentRow = 0;
this.currentColumn = 0;
this.cells = [];
},
renderItem : function(c, position, target) {
if (c && !c.rendered) {
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
}
},
getAnchorViewSize : function(ct, target){
return target.dom == document.body ? target.getViewSize() : target.getStyleSize();
},
onLayout : function(ct, target) {
Ext.ux.TableFormLayout.superclass.onLayout.call(this, ct, target);
var viewSize = this.getAnchorViewSize(ct, target);
var aw, ah;
if (ct.anchorSize) {
if (typeof ct.anchorSize == "number") {
aw = ct.anchorSize;
} else {
aw = ct.anchorSize.width;
ah = ct.anchorSize.height;
}
} else {
aw = ct.initialConfig.width;
ah = ct.initialConfig.height;
}
var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
var x,w,h;
for (i = 0; i < len; i++) {
c = cs[i];
// get table cell
x = c.getEl().parent(".x-table-layout-cell");
// set table cell width
x.setWidth((viewSize.width / this.columns) * (c.colspan || 1));
// get cell width (-10 for spacing between cells) & height to be base width of anchored component
w = x.getWidth() - 10;
h = x.getHeight();
if (c.anchor) {
a = c.anchorSpec;
if (!a) {
var vs = c.anchor.split(" ");
c.anchorSpec = a = {
right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
};
}
cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;
if (cw || ch) {
c.setSize(cw || undefined, ch || undefined);
}
}
}
},
parseAnchor : function(a, start, cstart) {
if (a && a != "none") {
var last;
if (/^(r|right|b|bottom)$/i.test(a)) {
var diff = cstart - start;
return function(v) {
if (v !== last) {
last = v;
return v - diff;
}
};
} else if (a.indexOf("%") != -1) {
var ratio = parseFloat(a.replace("%", "")) * .01;
return function(v) {
if (v !== last) {
last = v;
return Math.floor(v * ratio);
}
};
} else {
a = parseInt(a, 10);
if (!isNaN(a)) {
return function(v) {
if (v !== last) {
last = v;
return v + a;
}
};
}
}
}
return false;
},
adjustWidthAnchor : function(value, comp) {
return value - (comp.isFormField ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
},
adjustHeightAnchor : function(value, comp) {
return value;
}
});

Ext.Container.LAYOUTS["tableform"] = Ext.ux.TableFormLayout;


Hope this helps guys!

mdissel
9 Nov 2008, 2:00 PM
Thanks!

One minor fix, check for the getSize function in the doLayout


if (c.setSize && (cw || ch)) {
c.setSize(cw || undefined, ch || undefined);
}

JamesC
9 Nov 2008, 3:50 PM
Cool cheers, that bit comes straight from AnchorLayout, guess its a problem there too, not that I've seen it manifest itself!

mdissel
10 Nov 2008, 1:41 AM
I'm using buttons in my form and they don't support setSize (not needed, buttons should have the fixed width)

Animal
10 Nov 2008, 3:42 AM
Buttons do not extend BoxComponent in Ext 2.*.

You are a premium, use the bleeding edge code from SVN! You get a few bugs, but you can usually workaround with an override until Jack fixes them!

JamesC
23 Jan 2009, 3:39 PM
Made a minor adjusment to this to fix some layout issues on resize, here's the code:



Ext.namespace("Ext.ux");

Ext.override(Ext.layout.ContainerLayout, {
fieldTpl: (function() {
var t = new Ext.Template(
'<div class="x-form-item {5}" tabIndex="-1">',
'<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>',
'<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
'</div><div class="{6}"></div>',
'</div>'
);
t.disableFormats = true;
return t.compile();
})()
});

Ext.ux.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
monitorResize: true,
setContainer: function() {
Ext.layout.FormLayout.prototype.setContainer.apply(this, arguments);
this.currentRow = 0;
this.currentColumn = 0;
this.cells = [];
},
renderItem : function(c, position, target) {
if (c && !c.rendered) {
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext.get(this.getNextCell(c)));
}
},
getAnchorViewSize : function(ct, target){
return target.dom == document.body ? target.getViewSize() : target.getStyleSize();
},
onLayout : function(ct, target) {
Ext.ux.TableFormLayout.superclass.onLayout.call(this, ct, target);
if (!target.hasClass("x-table-form-layout-ct")) {
target.addClass("x-table-form-layout-ct");
}
var viewSize = this.getAnchorViewSize(ct, target);
var aw, ah;
if (ct.anchorSize) {
if (typeof ct.anchorSize == "number") {
aw = ct.anchorSize;
} else {
aw = ct.anchorSize.width;
ah = ct.anchorSize.height;
}
} else {
aw = ct.initialConfig.width;
ah = ct.initialConfig.height;
}
var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
var x, w, h;
for (i = 0; i < len; i++) {
c = cs[i];
// get table cell
x = c.getEl().parent(".x-table-layout-cell");
// get cell width
w = (viewSize.width / this.columns) * (c.colspan || 1);
// set table cell width
x.setWidth(w);
// get cell width (-10 for spacing between cells) & height to be base width of anchored component
w = w - 10;
h = x.getHeight();
// perform anchoring
if (c.anchor) {
a = c.anchorSpec;
if (!a) {
var vs = c.anchor.split(" ");
c.anchorSpec = a = {
right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
};
}
cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;
if (cw || ch) {
c.setSize(cw || undefined, ch || undefined);
}
}
}
},
parseAnchor : function(a, start, cstart) {
if (a && a != "none") {
var last;
if (/^(r|right|b|bottom)$/i.test(a)) {
var diff = cstart - start;
return function(v) {
if (v !== last) {
last = v;
return v - diff;
}
};
} else if (a.indexOf("%") != -1) {
var ratio = parseFloat(a.replace("%", "")) * .01;
return function(v) {
if (v !== last) {
last = v;
return Math.floor(v * ratio);
}
};
} else {
a = parseInt(a, 10);
if (!isNaN(a)) {
return function(v) {
if (v !== last) {
last = v;
return v + a;
}
};
}
}
}
return false;
},
adjustWidthAnchor : function(value, comp) {
return value - (comp.isFormField ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
},
adjustHeightAnchor : function(value, comp) {
return value;
}
});

Ext.Container.LAYOUTS["tableform"] = Ext.ux.TableFormLayout;


The bit changed is:


w = (viewSize.width / this.columns) * (c.colspan || 1);
// set table cell width
x.setWidth(w);
// get cell width (-10 for spacing between cells) & height to be base width of anchored component
w = w - 10;
h = x.getHeight();


Previously it was doing a setWidth() then a getWidth(), however the getWidth would sometimes return a different width to what had been set. This now fixes that problem.

Also a tip for anyone having layout issues (I finally solved this last week) - Make sure your fieldset's are anchor: "100%" if they're inside your form. I had not specified this and as such the form did not fully resize due to the fieldset having no anchoring!

JamesC
10 Feb 2009, 7:31 AM
Another addition to make this work with 2.2.1, you need to add:



getLabelStyle : Ext.layout.FormLayout.prototype.getLabelStyle


to the extend since this is a new method which would not have existed (since we are calling FormLayout superclass but extending tablelayout

Animal
10 Feb 2009, 7:49 AM
Have you updated the code in post #1 to keep up with all these changes? I think it's a very useful UX, and I often point people at it when they want fields layed out in a tabular fashion.

Animal
10 Feb 2009, 7:50 AM
Or perhaps start your own new thread with the latest and greatest code in, and I'll lock this one and let it die.

JamesC
12 Feb 2009, 12:22 PM
Since I'm not the OP and he isn't maintaining it anymore I've created a new thread here (http://extjs.com/forum/showthread.php?t=59897) which I will try to maintain! Guess you can close this thread now Animal.

ing.amdangelo
4 Jan 2012, 6:28 AM
In this case not exist the getForm() metod ??

Right ??

It is impossible p.getform.isvalid()