PDA

View Full Version : Ext.layout.TableFormLayout (v2)



JamesC
12 Feb 2009, 12:20 PM
This is a replacement for the old unmaintained TableFormLayout (here (http://extjs.com/forum/showthread.php?t=39342)), and allows form elements to be rendered in a table. It supports anchoring and the standard table layout column spanning etc.

Code is attached and can be dropped directly into examples directory

N.B
The columnWidths in the layoutConfig are optional, if not specified the columns will be evenly distributed.

-------------------------------- 3.0 update
Currently this is not supported by ext js 3.0 due to the overriding of fieldTpl in container layout which breaks *everything*. I'm working on a 3.0 compatible version (nearly finished), but will post it in the 3.0 forums when its done and the forums exist...

Einar
13 Feb 2009, 9:46 AM
I would like to be able to hide some of the form fields depending on the current user's role. If I hide a textfield, only the text field it self gets hidden, not the fieldlabel. I'm not very familiar with forms in ExtJs in general so I don't know if this is also the case when the layout is set to "form".

Shouldn't the label get display:none when I set the hidden configuration property?


{
xtype: "textfield",
fieldLabel: "Password",
allowBlank: false,
hidden:true
}

JamesC
13 Feb 2009, 12:03 PM
I believe this is a known issue in extjs form fields and not related to this extension... suggest you seach elsewhere on the forums for it!

ComputerSnacks
20 Feb 2009, 5:14 AM
Is there a way to apply a class to an individual row in a table?

I'd like to apply a background image to certain rows and individually applying the class to the cells individually does not produce the desired effect.

ComputerSnacks
20 Feb 2009, 5:17 AM
@Einar:

You may want to try setting the hideLabel property on the form items you want to hide to true:

{
xtype: "textfield",
fieldLabel: "Password",
allowBlank: false,
hidden:true,
hideLabel: true
}

durlabh
17 Apr 2009, 1:07 PM
Is there a way to set different labelWidths for different columns?

JamesC
17 Apr 2009, 1:13 PM
Nope that's not supported at the minute sorry!

durlabh
20 Apr 2009, 12:51 PM
In my case, in TableFormLayout, I needed to specify individual labelWidths for columns. Hence, I expanded on the OP's code a bit. Now, you should be able to say something like:



{
xtype: 'panel',
layout: 'tableform',
border: false,
layoutConfig: { columns: 2, columnWidths: [0.65, 0.35], columnLabelWidths: [73, 20] },
items: [
{ fieldLabel: 'Created By:', xtype: 'textfield', colspan: 2 },
{ fieldLabel: 'Creation Date:', xtype: 'datefield' },
{ fieldLabel: 'to:', xtype: 'datefield' },
{ fieldLabel: 'Modified By', xtype: 'textfield', colspan: 2 },
{ fieldLabel: 'Modified Date:', xtype: 'datefield' },
{ fieldLabel: 'to:', xtype: 'datefield' }
]
}



Here are the changes:



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) {
var cell = Ext.get(this.getNextCell(c));
cell.addClass("x-table-layout-column-" + this.currentColumn);
if (c && !c.rendered && c.isFormField && c.inputType != 'hidden') {
var elementStyle = this.elementStyle;
var labelStyle = this.labelStyle;

if (this.columnLabelWidths) {
var labelWidth = this.columnLabelWidths[this.currentColumn];
if (labelWidth) {
var pad = (typeof this.labelPad == 'number' ? this.labelPad : 5);
labelStyle = "width:" + labelWidth + "px;";
elementStyle = "padding-left:" + (labelWidth + pad) + 'px';
}
}

var args = [
c.id, c.fieldLabel,
this.getLabelStyle(labelStyle, c.labelStyle),
elementStyle || '',
typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
(c.itemCls || this.container.itemCls || '') + (c.hideLabel ? ' x-hide-label' : ''),
c.clearCls || 'x-form-clear-left'
];
if (typeof position == 'number') {
position = cell.dom.childNodes[position] || null;
}
if (position) {
this.fieldTpl.insertBefore(position, args);
} else {
this.fieldTpl.append(cell, args);
}
c.render('x-form-el-' + c.id);
} else {
Ext.layout.FormLayout.superclass.renderItem.call(this, c, 0, cell);
}
}
},
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, j, c, a, cw, ch;
var x, w, h, col, colWidth, offset;
for (i = 0; i < len; i++) {
c = cs[i];
// get table cell
x = c.getEl().parent(".x-table-layout-cell");
if (this.columnWidths) {
// get column
col = parseInt(x.dom.className.replace(/.*x\-table\-layout\-column\-([\d]+).*/, "$1"));
// get cell width (based on column widths)
colWidth = 0, offset = 0;
for (j = col; j < (col + (c.colspan || 1)); j++) {
colWidth += this.columnWidths[j];
offset += 10;
}
w = (viewSize.width * colWidth) - offset;
} else {
// 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;
},
getLabelStyle: function(labelBaseStyle, s) {
var ls = '', items = [labelBaseStyle, s];
for (var i = 0, len = items.length; i < len; ++i) {
if (items[i]) {
ls += items[i];
if (ls.substr(-1, 1) != ';') {
ls += ';'
}
}
}
return ls;
}
});

MacSimon
14 May 2009, 7:11 AM
Hi,

I've implemented the TableFormLayout and it works quite nicely for me.
I just have one problem.

I would like to vertically align a cell to the top (the cell has a rowspan and is now centered)

Thanks

dreas
15 May 2009, 12:04 AM
Any news on the 3.0 compatible version?

JamesC
15 May 2009, 8:57 AM
Here's an initial attempt, let me know of your findings:



Ext.namespace("Ext.ux.layout");

Ext.ux.layout.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) {
var cell = Ext.get(this.getNextCell(c));
cell.addClass("x-table-layout-column-" + this.currentColumn);
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, cell);
}
},
getAnchorViewSize : Ext.layout.AnchorLayout.prototype.getAnchorViewSize,
getTemplateArgs : Ext.layout.FormLayout.prototype.getTemplateArgs,
onLayout : function(ct, target) {
Ext.ux.layout.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, j, c, a, cw, ch;
var x, w, h, col, colWidth, offset;
for (i = 0; i < len; i++) {
c = cs[i];
// get table cell
x = c.getEl().parent(".x-table-layout-cell");
if (this.columnWidths) {
// get column
col = parseInt(x.dom.className.replace(/.*x\-table\-layout\-column\-([\d]+).*/, "$1"));
// get cell width (based on column widths)
colWidth = 0, offset = 0;
for (j = col; j < (col + (c.colspan || 1)); j++) {
colWidth += this.columnWidths[j];
offset += 10;
}
w = (viewSize.width * colWidth) - offset;
} else {
// 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;
},
getLabelStyle : Ext.layout.FormLayout.prototype.getLabelStyle
});

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

dreas
18 May 2009, 3:58 AM
Seems to work fine with ExtJS 3.0 RC1.1 so far. Thanks a lot!

fangzhouxing
20 May 2009, 9:51 PM
It supports anchoring...

Can I turn off anchoring support? Because I want to get fixed form layout at different screen size.

Animal
20 May 2009, 11:50 PM
You don't have to specify an anchor config in the child items.

fangzhouxing
21 May 2009, 4:26 AM
Animal ,thank you for reply, but the 'tableform' layout by default supports anchoring, and I don't use anchor config in the child items in anyway!

MacSimon
22 May 2009, 3:25 AM
Hi,


N.B
The columnWidths in the layoutConfig are optional, if not specified the columns will be evenly distributed.


Is it possible to set a fixed width (in px) for the columns through the layoutConfig

freemanxp
24 May 2009, 10:01 PM
This is a replacement for the old unmaintained TableFormLayout (here (http://extjs.com/forum/showthread.php?t=39342)), and allows form elements to be rendered in a table. It supports anchoring and the standard table layout column spanning etc.

Code is attached and can be dropped directly into examples directory

N.B
The columnWidths in the layoutConfig are optional, if not specified the columns will be evenly distributed.

-------------------------------- 3.0 update
Currently this is not supported by ext js 3.0 due to the overriding of fieldTpl in container layout which breaks *everything*. I'm working on a 3.0 compatible version (nearly finished), but will post it in the 3.0 forums when its done and the forums exist...


Any news on the 3.0 compatible version?

dreas
25 May 2009, 1:21 AM
Any news on the 3.0 compatible version?
Check the first post on the second page.

mw-flow
30 Jun 2009, 1:05 AM
Seems to work fine with ExtJS 3.0 RC1.1 so far. Thanks a lot!

And still does work with 3.0 RC2.

anystrike
15 Apr 2010, 2:45 AM
this plugin allow to insert a item inside a specific position cell?
like this Ext.getCmp('table').insert(3,object)

Thanks

rraponi
2 Jun 2010, 10:51 AM
Code below, use layout: "tableform" and the items then support standard anchor configuration as well as being layed out in a table. Now has a labelSeparator and can trackLabels.




Ext.namespace("Ext.ux.layout");

Ext.ux.layout.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) {
var cell = Ext.get(this.getNextCell(c));
cell.addClass("x-table-layout-column-" + this.currentColumn);
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, cell);
}
},
getLayoutTargetSize : Ext.layout.AnchorLayout.prototype.getLayoutTargetSize,
getTemplateArgs : Ext.layout.FormLayout.prototype.getTemplateArgs,
onLayout : function(ct, target) {
Ext.ux.layout.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.getLayoutTargetSize(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 = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
var x, w, h, col, colWidth, offset;
for (i = 0; i < len; i++) {
c = cs[i];
// get table cell
x = c.getEl().parent(".x-table-layout-cell");
if (this.columnWidths) {
// get column
col = parseInt(x.dom.className.replace(/.*x\-table\-layout\-column\-([\d]+).*/, "$1"));
// get cell width (based on column widths)
colWidth = 0, offset = 0;
for (j = col; j < (col + (c.colspan || 1)); j++) {
colWidth += this.columnWidths[j];
offset += 10;
}
w = (viewSize.width * colWidth) - offset;
} else {
// 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();
// If a child container item has no anchor and no specific width, set the child to the default anchor size
if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
c.anchor = this.defaultAnchor;
}

if(c.anchor){
a = c.anchorSpec;
if(!a){ // cache all anchor values
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){
boxes.push({
comp: c,
width: cw || undefined,
height: ch || undefined
});
}
}
}
for (i = 0, len = boxes.length; i < len; i++) {
c = boxes[i];
c.comp.setSize(c.width, c.height);
}
},

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;
},
// private
isValidParent : function(c, target){
return c.getPositionEl().up('table', 6).dom.parentNode === (target.dom || target);
},
getLabelStyle : Ext.layout.FormLayout.prototype.getLabelStyle,
labelSeparator : Ext.layout.FormLayout.prototype.labelSeparator,
trackLabels: Ext.layout.FormLayout.prototype.trackLabels
});
Ext.Container.LAYOUTS['tableform'] = Ext.ux.layout.TableFormLayout;

fethigurcan
21 Oct 2010, 3:20 AM
Hello, i have updated tablelayout to ExtJS 3.3 (added show, hide handlers of formlayout)



Code below, use layout: "tableform" and the items then support standard anchor configuration as well as being layed out in a table. Now has a labelSeparator and can trackLabels.




Ext.namespace("Ext.ux.layout");

Ext.ux.layout.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) {
var cell = Ext.get(this.getNextCell(c));
cell.addClass("x-table-layout-column-" + this.currentColumn);
Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, cell);
}
},
getLayoutTargetSize : Ext.layout.AnchorLayout.prototype.getLayoutTargetSize,
getTemplateArgs : Ext.layout.FormLayout.prototype.getTemplateArgs,
onLayout : function(ct, target) {
Ext.ux.layout.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.getLayoutTargetSize(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 = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
var x, w, h, col, colWidth, offset;
for (i = 0; i < len; i++) {
c = cs[i];
// get table cell
x = c.getEl().parent(".x-table-layout-cell");
if (this.columnWidths) {
// get column
col = parseInt(x.dom.className.replace(/.*x\-table\-layout\-column\-([\d]+).*/, "$1"));
// get cell width (based on column widths)
colWidth = 0, offset = 0;
for (j = col; j < (col + (c.colspan || 1)); j++) {
colWidth += this.columnWidths[j];
offset += 10;
}
w = (viewSize.width * colWidth) - offset;
} else {
// 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();
// If a child container item has no anchor and no specific width, set the child to the default anchor size
if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
c.anchor = this.defaultAnchor;
}

if(c.anchor){
a = c.anchorSpec;
if(!a){ // cache all anchor values
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){
boxes.push({
comp: c,
width: cw || undefined,
height: ch || undefined
});
}
}
}
for (i = 0, len = boxes.length; i < len; i++) {
c = boxes[i];
c.comp.setSize(c.width, c.height);
}
},

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;
},
// private
isValidParent : function(c, target){
return c.getPositionEl().up('table', 6).dom.parentNode === (target.dom || target);
},
getLabelStyle : Ext.layout.FormLayout.prototype.getLabelStyle,
labelSeparator : Ext.layout.FormLayout.prototype.labelSeparator,
trackLabels: Ext.layout.FormLayout.prototype.trackLabels,
onFieldShow: Ext.layout.FormLayout.prototype.onFieldShow,
onFieldHide: Ext.layout.FormLayout.prototype.onFieldHide,
});
Ext.Container.LAYOUTS['tableform'] = Ext.ux.layout.TableFormLayout;

infonoide
11 Aug 2011, 5:40 AM
CompositeField fields does not appears on screen.