PDA

View Full Version : [2.x] Field Override (appending other fields, and displaying help text)



Confused
21 Apr 2008, 8:25 AM
UPDATED: May, 17
- resolved rendering issue in IE when the first control is a combo box and it has one or more other controls appended to it

A few of my forms required one or more fields/labels be added to the right of an existing field in a form without having to go through the pain of using columns and them lining up. I also wanted the ability to add small print text below the field like help text. The attached override does just that, it allows you to append other fields within the same column as an existing field:



var form = new Ext.FormPanel({
id: 'form',
bodyStyle: 'padding: 10px',
border: false,
buttons: [{
text: 'Submit',
scope: this,
handler: function() {
Ext.getCmp('form').getForm().submit({ url: 'noscript.php' });
}
}],
items: [{
xtype: 'textfield',
name: 'text',
fieldLabel: 'TextField',
helpText: 'This is the help info for this group of widgets',
append: [{
xtype: 'datefield',
name: 'date'
}, {
xtype: 'button',
text: '...',
handler: function() {
alert('do something here');
}
}]
}, {
xtype: 'numberfield',
name: 'number',
fieldLabel: 'NumberField',
helpText: 'Only enter numbers'
}]
});


The code above will create the items illustrated in the attached image.

The coding may not be 100% and if you have alternate ways of doing things, I'm all ears.

bhaidaya
21 Apr 2008, 5:38 PM
this looks interesting.. Cant wait to try it.. keep it up.

garraS
21 Apr 2008, 7:44 PM
Nice!
Thanks!

manube
23 Apr 2008, 12:21 AM
Thanks!!!

First tests are OK. Very useful!!

=D>=D>=D>

JorisA
23 Apr 2008, 12:53 AM
I was also looking for a way to join multiple fields (for example with dates: from ... to ... ) so thnx, Ill have a look at it later.

gelleneu
23 Apr 2008, 11:48 PM
It should be included in the next Ext Release!! Great!

At the moment I try to append a combobox, but it doesn't work..

gelleneu
24 Apr 2008, 12:06 AM
OK, it was my mistake. But I have probably a new problem:

I have a form with 20 elements. In a special mode, some elements will be disabled (f.E. the first 10 elements). If the items.get selector meets the "double" field, only the first item will be disabled or enabled... Hmm.

Confused
24 Apr 2008, 6:54 AM
Tnx all... I didn't run the code through too much testing nor have had the chance to play with it more than what's in the example code. I put it through its paces and see if I can resolve some of the issues. I have been curious how it would look with text areas and other widgets. This new functionality should probably be disabled when someone is trying to create a control in a Editor Grid. And I will take a look at enabling/disabling the appended widgets.

gelleneu
24 Apr 2008, 11:31 PM
It's a great snippet of code, I used embedded layouts in my forms before, but that's not the best solution.

Testing your code in IE7 with ExtJS 2.1 failed, because in the wrap and createChild configs, there is a config attribute "class". You have to change it to "cls" and it works in FF AND IE.

The missing disable function is a little curios: the appended field is not a part of my formular (it seems so): I disable my fields in this way (pseudo code).

for (i = 0..){

form.items.get(i).disable();

}

That works for all items but not for the appended field. :-)

Confused
25 Apr 2008, 12:07 AM
Tnx. I will apply these changes to the code.

wm003
25 Apr 2008, 11:41 AM
very nice idea and useful. thanks for sharing

CPliskin
29 Apr 2008, 4:06 AM
Hello!

Amazing idea :)

The only thing that I've fixed in your code - is the registration in parent form to make isValid/loadRecord form's methods handle appended fields.



Ext.form.Field.prototype.onRenderOriginal = Ext.form.Field.prototype.onRender;
Ext.override(Ext.form.Field, {
getForm: function(){
var form;
this.ownerCt.bubble(function(container){
if (container.form){
form = container.form;
return false;
}
}, this);

return form;
},

onRender: function(ct, position){
this.onRenderOriginal(ct, position);

// create the appended fields
var ac = this.append || [];
if (ac.length > 0) {
var form = this.getForm();

// create a wrap for all the fields including the one created above
this.wrap = this.el.wrap({ tag: 'div' });
// also, wrap the field create above with the same div as the appending fields
this.el.wrap({ tag: 'div', cls: 'x-form-append' });
for (var i = 0, len = ac.length; i < len; i++) {
// if the append field has append fields, delete this
delete ac[i].append;
// create a div wrapper with the new field within it.
var cell = this.wrap.createChild({ tag: 'div', cls: 'x-form-append' });
var field = new Ext.ComponentMgr.create(ac[i], 'button');
// render the field
field.render(cell);

if (form && field.isFormField)
form.items.add(field);
}
}

// if there is helpText create a div and display the text below the field
if (typeof this.helpText == 'string') {
this.wrap = this.wrap || this.el.wrap();
this.wrap.createChild({ tag: 'div', cls: 'x-form-helptext', html: this.helpText });
}
}
});


Also I had troubles in IE7 quirks mode with positions of the TriggerField inheritors (hadn't tested in IE6 and strict mode).

CSS fix is follows:


.ext-ie .x-form-append { position:relative; }

ajaxE
30 Apr 2008, 2:09 PM
I found that once the button is enabled or disabled. The state cannot be changed. That is, initially disabled button, cannot be enabled.

Please help! Do I miss anything?

Thanks.

ajaxvador
30 Apr 2008, 2:14 PM
great job=D>

Confused
30 Apr 2008, 10:01 PM
I have updated the code to resolve the reported issues (tnx: gelleneu & CPliskin). I have also added some more examples like enabling/disabling elements, displaying combos and datefields. It has been tested on IE and it seems to be working on both platforms.

ajaxE
1 May 2008, 6:14 PM
The new zip file cannot be opened after save. Would you please give a new download?

It's a great stuff. Cannot wait to try...

Thanks

Confused
1 May 2008, 6:24 PM
I downloaded it to two other machines and was able to extract the contents. Try downloading it again. If Windows is blocking you from extracting the content, use some other extraction tool. When this happens I use cygwin's unzip utility. If others complain about this same issue, I will upload the files as text files.

gelleneu
3 May 2008, 10:33 AM
Download works fine for me too. I'll try the new version tomorrow. Thanks @Confused!

Confused
3 May 2008, 10:39 AM
I forgot to include the stylesheet in the latest zip. So I have attached the same changes with the stylesheet included this time.

halkon_polako
3 May 2008, 11:09 AM
Can you attatch the new version of zips into the first post?
It will be easier to get the last version.
Thx for this extension.

Confused
3 May 2008, 11:57 AM
Sure thing

rfjacobsen
6 May 2008, 7:58 AM
This is a great implementation and I have gotten it to work for the fields I need it to work for.
However, no matter what field type I use, titles do not get displayed in either FF or IE.

Am I missing something?

Thanks.

RJ

Confused
6 May 2008, 5:35 PM
If titles you are referring to fieldLabels, I am aware that appended widgets do not display their fieldLabels. Only the widget that has the append list shows the fieldLabel. Although it wasn't purposely coded this way, I haven't found a case where I would want the labels for the appended widgets. The idea originated from needing a way to add a button to the right side of a text box, also trying to add a label to the right side of a widget. Initially I was going to code this to only append one widget, but found that there might be cases where I needed to append a label and then another text box.

If someone has a patch to apply to allow for fieldLabels in the appended widgets, I will be glad to apply it to the code and publish the code.

rymoore9999
14 May 2008, 1:12 PM
I see that you've made the fix to append a combobox, but has anyone tried appending a field to a combobox? I can't seem to get it to work.

Confused
17 May 2008, 5:54 PM
rymoore9999, I have uploaded a newer version which resolves this issue. You can now have a combo box with appended controls.

VinceChen
26 May 2008, 6:19 PM
Excuse me. I try to use this plugins to implement dynamically add a set of form field (compose of two combos). It works well. But when I select value in any first combo of any set of form field. It always changes the value in the first combo of the "first set of form field". Does anyone encounter the same situation?

Confused
26 May 2008, 6:41 PM
Can you send me your code at arkconfused at hotmail.com?

VinceChen
27 May 2008, 1:29 AM
Thanks very much. I will make a sample to you.

VinceChen
27 May 2008, 1:41 AM
Sorry for that. My last question may not be a "question". It could work well on my another sample codes.
And I have an another question. How could I dynamically remove a set of form fields?

bhaidaya
28 May 2008, 9:12 PM
This is great stuff...
I started to use this on a new app and revamped it a little.. so I thought i'd share.

First of all its in plugin form now and second of all I broke it into two plugins 'inlineItems' and 'helpText' as well as renamed it. They are two different functions (but very similar).

I also added new config options to both plugins and did away with the css files...

Ext.ux.plugins.InlineItems
InlineItemLabel: a label that shows up directly below the item. (same as help text)
InlineItemLabelClass: the css class that can override the default style (this defaults to your original css file settings)

{
fieldLabel: 'Legal Name',
name: 'LegalFirstName',
allowBlank: false,
plugins: [Ext.ux.plugins.InlineItems],
inlineItemLabel: 'First',

inlineItems: [{
xtype: 'textfield',
inlineItemLabel: 'Middle',
name: 'LegalMiddleName'
}, {
xtype: 'textfield',
inlineItemLabel: 'Last',
name: 'LegalLastName',
allowBlank: false
}]
}

Ext.ux.plugins.HelpText
helpText: help text that shows up directly below the item. (same as before)
helpTextClass: the css class that can override the default style..


{
fieldLabel: 'Website',
name: 'Website',
plugins: [Ext.ux.plugins.HelpText],
helpText: 'eg. http://www.example.com',
vtype: 'url'
}

They do not need each other and frankly you probably won't want to use both... but it will work... on any container I think..

VinceChen
30 May 2008, 6:20 PM
Thank you at first.
I'll try this good component.

VinceChen
31 May 2008, 6:51 PM
Have you every tried to used combobox with a lineItem of textfield?
The screen will look so strange.

bt_bruno
31 Jul 2008, 5:56 AM
Append funcionality is great! Thanks for the ux!

But please report this :


var field = new Ext.ComponentMgr.create(ac[i], 'button');

You create a new component based on the append definition. Ok...if you're using lazy rendering...

Works perfect

...,append:[{
xtype:'button'
text:'myButton'
}]//works

But if I want to create the component and save it's reference, the reference is lost because you're creating a new component on Ext.ComponentMgr.create


,append :[this.myButton= new Ext.Button({
text:'myButton'
})]//loses reference

Soo I corrected using this :

var field = Ext.ComponentMgr.get(ac[i].id||'') || new Ext.ComponentMgr.create(ac[i], 'button');

Try to get the component by ID, if it doesn't exists, create it!

;)

Cheers

damien
31 Aug 2008, 2:06 AM
I like this plugin. Only problem i am having is the fact that the fields allowBlank option does not work. If i submit the form the validation off the fields does not work.

mabello
10 Sep 2008, 1:43 AM
I'm using the extension, and it suites my need very well, so thanks a lot!

Just a couple of things, since Ext.ComponentMgr is a singleton, it would be good to avoid the new keyword:
(var field = Ext.ComponentMgr.create(ac[i], 'button'); without new.

I have just added the function appendFields that accept an array of fields, just in case you have already create your component (new Ext.form.Combo({}) ) instead of using the lazy creation of it using just the config obj), and you want to append fields to it.

Same thing for the helpText, I've just added a setHelpText function that take a string as input parameter.

In reality, you could avoid to use this functions, since you could just add the properties to the object that has already been created (but not rendered of course), but it seems to me more neat to use methods.



,setHelpText: function(helpText){
if(this.rendered)
return;
this.helpText = helpText;
}

,appendFields: function(fieldsArray){
if(this.rendered)
return;
if(!fieldsArray || fieldsArray == null || !Ext.isArray(fieldsArray))
return;
if(!this.append)
this.append = fieldsArray;
else
this.append = this.append.concat(fieldsArray);
}


Cheers and keep up the good work.

chuckdev
12 Sep 2008, 11:35 PM
I use the field append component, it display correctly on the same line.
but how can I set the append value?

For my example, I tried Ext.getCmp('clientName').setValue('test value'); but it seems not to work!
any idea how to set the value?

here my code:
[code]
var formPanel = new Ext.FormPanel({
id: 'billingForm',
frame: true,
labelAlign: 'left',
title: 'Facture',
bodyStyle:'padding:5px',
width: 1100,
layout: 'column',
items: [
{
columnWidth: 0.4,
xtype: 'fieldset',
labelWidth: 90,
defaults: {width: 140}, // Default config options for child items
defaultType: 'textfield',
autoHeight: true,
bodyStyle: Ext.isIE ? 'padding:0 0 5px 15px;' : 'padding:10px 15px;',
border: false,
style: {
"margin-left": "10px", // when you add custom margin in IE 6...
"margin-right": Ext.isIE6 ? (Ext.isStrict ? "-10px" : "-13px") : "0" // you have to adjust for it somewhere else
},
items: [
{
xtype: 'datefield',
fieldLabel: 'Date',
id: 'date',
name: 'date'
},
{
fieldLabel: 'ClientID',
id: 'clientId',
name: 'clientId',
width: 30,
append: [{
xtype: 'fieldset',
fieldLabel: 'Client Name',
id: 'clientName',
name: 'clientName',
width: 130
}]
},{
fieldLabel: 'Facturer

mabello
13 Sep 2008, 4:38 AM
Dear chuckdev,


append: [{
xtype: 'fieldset',
fieldLabel: 'Client Name',
id: 'clientName',
name: 'clientName',
width: 130
}]


You are appending a fieldSet of id 'clientName', but the fieldSet does not have a setValue method of course, it's just a container of fields, so Ext.getCmp('clientName').setValue() does not make sense.
I think that's the only problem :)

chuckdev
13 Sep 2008, 7:32 AM
the setValue() function is working, but not when the fieldset is in the append field.
This code is working Ext.getCmp('clientId').setValue('5555'));
but not Ext.getCmp('clientName').setValue('testxxxx')); because it is inside the append field!
weird!

if someone has a clue let me know!

chuckdev
13 Sep 2008, 8:01 AM
ok I was able to fix it by using xtype: 'textfield' instead of xtype: 'fieldset'
the Ext.getCmp('clientName').setValue('testxxxx')); is working perfectly now!
append: [{
xtype: 'textfield',
fieldLabel: 'Client Name',
id: 'clientName',
name: 'clientName',
width: 130
}]

aleksandy
18 Sep 2008, 6:42 PM
Have you every tried to used combobox with a lineItem of textfield?
The screen will look so strange.

I made so:

// create namespace for plugins
Ext.namespace('Ext.ux.plugins');
Ext.ux.plugins.InlineItems = {
init: function(container){
Ext.apply(container, {
onRender: container.onRender.createSequence(function(ct, position){
// create the appended fields
var ac = this.inlineItems || [];
ac = Ext.isArray(ac) ? ac : [ac];


if (ac.length > 0) {
var form = this.getForm();
if (!this.trigger) {
// create a wrap for all the fields including the one created above
this.wrap = this.el.wrap({
tag: 'div'
});

// also, wrap the field create above with the same div as the appending fields
this.el.wrap({
tag: 'div',
cls: 'x-form-append',
style: 'float: left; padding-right: 3px;'
});
var wrpr = this.wrap;
} else {
var wrpr = this.wrap.wrap({
tag: 'div'
});
this.wrap.wrap({
tag: 'div',
cls: 'x-form-append',
style: 'float: left; padding-right: 3px;'
});
}

for (var i = 0, len = ac.length; i < len; i++) {
// if the append field has append fields, delete this
delete ac[i].inlineItems;
// create a div wrapper with the new field within it.
var cell = wrpr.createChild({
tag: 'div',
cls: 'x-form-append',
style: 'position: relative; float: left;padding-right: 3px;'
});
var field = Ext.ComponentMgr.create(ac[i], 'button');
// render the field
field.render(cell);
cell.createChild({
tag: 'div',
cls: typeof ac[i].inlineItemLabelClass != 'undefined' ? ac[i].inlineItemLabelClass : '',
style: typeof ac[i].inlineItemLabelClass != 'undefined' ? 'clear: both;' : 'clear: both; font-size: 9px; color: #888888;',
html: ac[i].inlineItemLabel
});

if (form && field.isFormField) {
form.items.add(field);
}
}
};

//Add the inline label if it's available
if (typeof this.inlineItemLabel == 'string') {
wrpr = !this.trigger ?
this.wrap = this.el.wrap({tag: 'div'}) :
this.wrap.wrap({tag: 'div'});
wrpr.createChild({
tag: 'div',
cls: typeof this.inlineItemLabelClass != 'undefined' ? this.inlineItemLabelClass : '',
style: typeof this.inlineItemLabelClass != 'undefined' ? 'clear: both;' : 'clear: both; font-size: 9px; color: #888888;',
html: this.inlineItemLabel
});
};
}),
getForm: function(){
var form;
this.ownerCt.bubble(function(container){
if (container.form) {
form = container.form;
return false;
}
}, this);

return form;
} // end of function onRender
});

} // end of function init
}
Ext.ux.plugins.InlineItems = Ext.extend(Ext.ux.plugins.InlineItems, Ext.util.Observable);
// end of file

mjlecomte
20 Sep 2008, 4:37 AM
Please consider adding this to the repository. I was trying to help someone else in the forums and point them to this extension and it took me over 10 minutes just to find it. I about gave up looking. :)

vtswingkid
22 Sep 2008, 12:42 PM
You could try ux.form.fieldpanel ... it is in the learning section under 2.0 extensions.

csextjs
24 Sep 2008, 7:08 AM
Thanks for sharing this great code.
However if I have more than one helpText in a row, the very first
helpText drops. See attached.


items: [{
xtype: 'textfield',
name: 'lname',
width: 100,
fieldLabel: 'Name',
helpText: 'Last Name',
append: [{
xtype: 'textfield',
width: 100,
helpText: 'First Name',
name: 'fname1'

}, {
xtype: 'textfield',
width: 100,
helpText: 'Mid. Name',
name: 'mname1'
}]
}, {
xtype: 'numberfield',
name: 'number',
width: 175,
fieldLabel: 'NumberField',
helpText: 'Only enter numbers'
}
]
Anyone has any solution for this?
Thanks.

mabello
24 Sep 2008, 7:43 AM
Hey there,

I fixed it.

Change this:


if (typeof this.helpText == 'string') {
this.wrap = this.wrap || this.el.wrap();
this.wrap.createChild({ tag: 'div', cls: 'x-form-helptext', html: this.helpText });
}

with this


// if there is helpText create a div and display the text below the field
if (typeof this.helpText == 'string') {
this.wrap = this.el.wrap() || this.wrap;//<--------------------
this.wrap.createChild({ tag: 'div', cls: 'x-form-helptext', html: this.helpText });
}

Hope this helps

csextjs
24 Sep 2008, 4:07 PM
Thanks for the quick fix.
I've applied the change and it worked.

Thanks again.
Best Regards.

sksoft
25 Sep 2008, 6:45 AM
It seems that it has problems with Ext.form.FileUploadField control (from Ext 2.2 examples)

temporary
30 Oct 2008, 4:49 AM
It would be nice if the helptext div would respect anchoring as well. Right now it doesn't grow or shrink the same way the input field does.

RealMezcal
10 Dec 2008, 12:29 PM
Thanks for sharing this code. One question...can i use anchoring in child (append) fields? Setting width for each field is not good for me.

galdaka
10 Dec 2008, 2:47 PM
All in one file. I create the stylesheet inside Fieldoverride.js.

Live example: www.jadacosta.es/extjs/examples/helpText/index.html (http://www.jadacosta.es/extjs/examples/helpText/index.html)

I attach simple Drag&drop to extjs examples folder example.

Greetings,

galdaka
10 Dec 2008, 2:50 PM
It would be nice if the helptext div would respect anchoring as well. Right now it doesn't grow or shrink the same way the input field does.

Combine it with Fit to parent plugin: http://extjs.com/forum/showthread.php?t=28318

Greetings,

accilies
22 Jan 2009, 12:33 AM
rymoore9999, I have uploaded a newer version which resolves this issue. You can now have a combo box with appended controls.
Appending to a combo does not work. Some CSS issue it seems:

http://www.snackfeed.com/plugin/thumbnails/ab97ab7f391f8378cb76ba0ceb662209.png

Scorpie
22 Jan 2009, 4:14 AM
Nice! Good job!

sethend
4 May 2009, 6:02 AM
Nice job. One question, how to add fieldLabel in the other fields (the fields that are inside "append")?

mabello
4 May 2009, 6:15 AM
@accilies
See the post #44, it should fix your problem...
Hope this helps

Confused
4 May 2009, 7:41 AM
Nice to see people still using the extension and in more ways that it was designed to. It's awesome. With that said, I had originally design the override to be able to add a field or two to the right of another field to simplify coding certain layouts. The solution I was trying to solve here was to be able to add a text field to a form and then a label to the immediated right. For example if I had a Weight text field I wanted to put a 'lb' label to the right. There are also times when I wanted to put in two textfields side by side. My thought was that appending other fields to another field would just create a single super field so things like fieldLabel and helpText weren't needed.

However, I am working on a project now where I could see the benefit of creating individual fields with fieldLabel and helpText which are appended. Another override or plugin that could be a nice to have in that case is a horizontal form layout where the controls are laid out horizontally instead of virtically. I know there is a column layout, and I believe there is a new layout in 3.0 that does horizontal layouts (I haven't looked to deeply into this yet), but to simplify things it would be nice to specify the orientation of the form.

For example, I have a form in my new project that has 5 textfields and a button. They are arranged from left to right. To do this, I would have to use the column layout adding another layer to my form's code. Instead, it would be easier to just specify in the form config that I want horizontal layout and not have to use the column layout. In my case, I don't need the fields to be in columns.

As for this override, I will take all the suggestions, code patches and merge them into the original code. I'll make this available when it's done. It's actually too bad that something like this override wasn't applied to the latest release of ExtJS. There is so many applications where you can append fields to other fields when doing screen layouts.

accilies
4 May 2009, 8:20 PM
Thanks Mabello,

I will try it.


@accilies
See the post #44, it should fix your problem...
Hope this helps

accilies
4 May 2009, 8:23 PM
I think that will defeat the purpose of this extension. What you want is column layout of the form so that you have labels for each fields yet next to each other.


Nice job. One question, how to add fieldLabel in the other fields (the fields that are inside "append")?

jimtyp
19 May 2009, 11:38 AM
Very nice extension, you da man!

SimFox3
19 Jun 2009, 2:47 PM
What license is Field Override released under?

Nagiy
3 Jul 2009, 8:39 AM
I have been using this extension for a while and came across a few issues related to comboboxes and labels. I would like to share this fix with all of you :)

I also removed the dependency on the external CSS file.

I hope you enjoy this extension as much as I did. Thanks a lot Confused (http://extjs.com/forum/member.php?u=2759)



Ext.override(Ext.form.Field, {
getForm : function() {
var form;
this.ownerCt.bubble(function(container){
if (container.form) {
form = container.form;
return false;
}
}, this);

return form;
},

onRender : function(ct, position) {
Ext.form.Field.superclass.onRender.call(this, ct, position);
if(!this.el){
var cfg = this.getAutoCreate();
if(!cfg.name){
cfg.name = this.name || this.id;
}
if(this.inputType){
cfg.type = this.inputType;
}
this.el = ct.createChild(cfg, position);
}
var type = this.el.dom.type;
if(type){
if(type == 'password'){
type = 'text';
}
this.el.addClass('x-form-'+type);
}
if(this.readOnly){
this.el.dom.readOnly = true;
}
if(this.tabIndex !== undefined){
this.el.dom.setAttribute('tabIndex', this.tabIndex);
}
this.el.addClass([this.fieldClass, this.cls]);
this.initValue();
// everything above is from the original onRender function

// create the appended fields
var ac = this.append || [];
if (ac.length > 0) {
var form = this.getForm();

// create a wrap for all the fields including the one created above
this.wrap = this.el.wrap({ tag: 'div', style: 'zoom:1;' });
// also, wrap the field create above with the same div as the appending fields
this.el.wrap({
tag: 'div',
style: 'position: relative; float: left;' + (this.xtype=='label'? 'margin-top: 3px;' : '')
});
for (var i = 0, len = ac.length; i < len; i++) {
// if the append field has append fields, delete this
delete ac[i].append;
// create a div wrapper with the new field within it.
var cell = this.wrap.createChild({
tag: 'div',
style: 'position: relative; float: left; margin-left: 3px;' + (ac[i].xtype=='label'? 'margin-top: 3px;' : '')
});
var field = Ext.ComponentMgr.create(ac[i], 'button');
// render the field
field.render(cell);

if (form && field.isFormField) {
form.items.add(field);
}
}
}

// if there is helpText create a div and display the text below the field
if (typeof this.helpText == 'string') {
this.wrap = this.wrap || this.el.wrap();
this.wrap.createChild({
tag: 'div',
cls: typeof this.helpTextClass != 'undefined' ? this.helpTextClass : '',
style: typeof this.helpTextClass != 'undefined' ? 'clear: both;' : 'clear: both; font-size: 9px; color: #888;',
html: this.helpText
});
}
}
});

SchattenMann
22 Jul 2009, 3:31 AM
i'm having some problems using this with ext3.0...do some one else tried?

i've been around this for the past 3 hours with no results...

it seems one of the problems is that array append is always > 1 O.o

with ext 2.x we have



var ac = this.append || [];
console.debug(ac.length);
if (ac.length > 0) {...}
this will return 0 if field don't have anything to append and > 0 if it does...

but with ext 3.0 always returns a minimum of 1...canĀ“t understand why since the array is empty...

so 2 possible solutions:

1. change the name of array from append to something else (join, children or something)

2.check if append is an array with




function isArray(variable) {
return (variable.constructor == Array);
}

// create the appended fields
var ac = this.append || [];
if (ac.length > 0 && isArray(this.append)) {
...
}

so its solved. BUT at least one remains: all fields must have value defined or it will return
value is undefined
in the end (when all fields have value defined) the form is rendered only with labels..


----EDITED---

finally i was able to make it work in 3.0



Ext.override(Ext.form.Field, {
getForm : function() {
var form;
this.ownerCt.bubble(function(container){
if (container.form) {
form = container.form;
return false;
}
}, this);

return form;
},

onRender : function(ct, position) {
if(!this.el){
var cfg = this.getAutoCreate();

if(!cfg.name){
cfg.name = this.name || this.id;
}
if(this.inputType){
cfg.type = this.inputType;
}
this.autoEl = cfg;
}
Ext.form.Field.superclass.onRender.call(this, ct, position);

var type = this.el.dom.type;
if(type){
if(type == 'password'){
type = 'text';
}
this.el.addClass('x-form-'+type);
}
if(this.readOnly){
this.el.dom.readOnly = true;
}
if(this.tabIndex !== undefined){
this.el.dom.setAttribute('tabIndex', this.tabIndex);
}

this.el.addClass([this.fieldClass, this.cls]);
// everything above is from the original onRender function in ext 3.0

function isArray(variable) {
return (variable.constructor == Array);
}

// create the appended fields
var ac = this.append || [];

//check if append is array
if (ac.length > 0 && isArray(this.append)) {
var form = this.getForm();
// create a wrap for all the fields including the one created above
this.wrap = this.el.wrap({ tag: 'div', style: 'zoom:1;' });
// also, wrap the field create above with the same div as the appending fields
this.el.wrap({
tag: 'div',
style: 'position: relative; float: left;' + (this.xtype=='label'? 'margin-top: 3px;' : '')
});
for (var i = 0, len = ac.length; i < len; i++) {
// if the append field has append fields, delete this
delete ac[i].append;
// create a div wrapper with the new field within it.
var cell = this.wrap.createChild({
tag: 'div',
style: 'position: relative; float: left; margin-left: 3px;' + (ac[i].xtype=='label'? 'margin-top: 3px;' : '')
});
var field = Ext.ComponentMgr.create(ac[i], 'button');
// render the field
field.render(cell);

if (form && field.isFormField) {
form.items.add(field);
}
}
}

// if there is helpText create a div and display the text below the field
if (typeof this.helpText == 'string') {
this.wrap = this.wrap || this.el.wrap();
this.wrap.createChild({
tag: 'div',
cls: typeof this.helpTextClass != 'undefined' ? this.helpTextClass : '',
style: typeof this.helpTextClass != 'undefined' ? 'clear: both;' : 'clear: both; font-size: 9px; color: #888;',
html: this.helpText
});
}
}
});


its the first time i do such thing so its probably not the best approach...but hell: it worked!

JoeAtTrends
29 Jul 2009, 1:51 PM
I found that the conflict with ExtJs 3.0 and this override is that there is now an append function (undocumented?:-?). I think it is new and not quite working for all fields, but it appends a value to the fields value. Since that will be present on all fields you will always end up inside that if block and probably like I did have an error around delete ac[ i ].inlineItems;

This is what I did, it is a mix of the most recent version and the plugin versions posted here (http://extjs.com/forum/showthread.php?p=174743#post174743). (thanks bhaidaya)



Ext.override(Ext.form.Field, {
getForm : function() {
var form;
this.ownerCt.bubble(function(container){
if (container.form) {
form = container.form;
return false;
}
}, this);

return form;
},

onRender : Ext.form.Field.prototype.onRender.createSequence(function(ct, position) {
// The parts from the original onRender were removed and replaced with the
// create sequence method of extending the function, this is in part due to
// changes in the 3.0 logic for onRender and also to perserve any future changes

// create the appended fields
var ac = this.inlineItems || [];
//Updated to allow a single item
//be added without being in an array
ac = Ext.isArray(ac) ? ac : [ac];

if (ac.length > 0) {
var form = this.getForm();

// create a wrap for all the fields including the one created above
this.wrap = this.el.wrap({ tag: 'div', style: 'zoom:1;' });
// also, wrap the field create above with the same div as the appending fields
this.el.wrap({
tag: 'div',
style: 'position: relative; float: left;' + (this.xtype=='label'? 'margin-top: 3px;' : '')
});
for (var i = 0, len = ac.length; i < len; i++) {
// if the append field has append fields, delete this
// Note: This can be removed now that ownerCt is being assigned to inline fields
delete ac[i].inlineItems;
// create a div wrapper with the new field within it.
var cell = this.wrap.createChild({
tag: 'div',
style: 'position: relative; float: left; margin-left: 3px;' + (ac[i].xtype=='label'? 'margin-top: 3px;' : '')
});
var field = Ext.ComponentMgr.create(ac[i], 'button');
//Assign the owner container
field.ownerCt = this.ownerCt;
// render the field
field.render(cell);

if (form && field.isFormField) {
form.items.add(field);
}
}
}

// if there is helpText create a div and display the text below the field
if (typeof this.helpText == 'string') {
this.wrap = this.wrap || this.el.wrap();
this.wrap.createChild({
tag: 'div',
cls: typeof this.helpTextClass != 'undefined' ? this.helpTextClass : '',
style: typeof this.helpTextClass != 'undefined' ? 'clear: both;' : 'clear: both; font-size: 9px; color: #888;',
html: this.helpText
});
}
})
});

First off I used the create sequence method of modifying the onRender (I am not sure if using the prototype is the correct way to do this in an override but it was the cleanest way I could find to reference the original function, and it works)

Then I changed this.append to this.inlineItems to avoid conflict with the new function

And the last change was that I added field.ownerCt = this.ownerCt;. Since these are being added to the container without the container knowing I figured there would be a few things that might error when those inline fields didn't have an ownerCt set. In fact the error I kept getting when first trying this in 3.0 was when they were being rendered, they would try and run the custom getForm function but fail on the bubbling, it hadn't dawned on me to check which field was actually being rendered at the time so it took me a while to finally pin down that the cause was the new Ext.form.Field.append function.

I think it could use some work to make the help text show more uniformly, like in the plugins how they can be shown for each field. If you put help text on one of the inline elements, it will render, but push the first fields help text down.. overall though this override has helped a lot, thanks Confused.

jasonb885
11 Aug 2009, 1:06 PM
I think it could use some work to make the help text show more uniformly, like in the plugins how they can be shown for each field. If you put help text on one of the inline elements, it will render, but push the first fields help text down.. overall though this override has helped a lot, thanks Confused.

I made a small change that seems to have resolved the helptext alignment issue when there's helptext and one or more inline items with helptext.



if (typeof this.helpText == 'string') {
//this.wrap = this.wrap || this.el.wrap();
this.wrap = this.el.wrap();


Seems to work.

jimtyp
18 Aug 2009, 9:27 AM
Got the version by SchattenMann working. The one by JoeAtTrends doesn't work for me, even with the modification provided by jasonb885.

I still have a problem though, the helptext for the initial field does not appear correctly, it's too far down, the ones in the append show up correctly:


{
xtype: 'textfield',
name: 'number',
fieldLabel: 'Street Address',
width: 200,
helpText: '<span style="padding-left: 2px"></span>Street Number',
append: [
{
xtype: 'textfield',
width: 200,
style: 'textTransform: uppercase',
helpText: 'Street Name'
}
,
{
xtype: 'textfield',
style: 'textTransform: uppercase',
helpText: '<span style="padding-left: 2px"></span>Unit',
width: 40
}
]
}

JoeAtTrends
18 Aug 2009, 9:36 AM
You are saying the help text for the first field in the line is down the height of the remaining ones? And that all of the other fields have their help text directly below the field, right?

JasonB885s fix should correct that placement issue, even if put in SchattenMann's version.


If you were having problems with the modification I had made on the original code, it may be because the config being used has been changed to avoid conflicts with version 3.0 of the ExtJs library (where a private append method was added to form field). Instead of using append: you will need to use inlineItems:If you do this and still have trouble I can review my changes and retest. I haven't been working on that much, but have done some investigation into the possibility of help text position (like putting larger paragraph help texts to the right of the fields or fieldsets, and placing them above the fields for tall select list type fields where the help text could easily be overlooked since it is so far down.)

jimtyp
18 Aug 2009, 9:44 AM
Sorry, it does work in 3.0. I was applying the change jasonb885 made to what JoeAtTrends provided. If I make the change to the version provided by SchattenMann, all works as it did in 2.2 :D

SchattenMann
18 Aug 2009, 12:05 PM
never had that problem but glad it worked...

one small question?

i you need help on first field? i say that because in my understanding append is useful when we need multiple fields but that basically are just one (for example a IP Address field my be divided in 4 fields :1 + 3 append)

if not it would be much more easy to use column forms...i think...

jimtyp
19 Aug 2009, 5:49 AM
Yes, I was using the append to provide things like street address, split into street number, name and unit (optional).

If you have a better way could you post it with some sample code?

SchattenMann
19 Aug 2009, 7:27 AM
the following code is part of tine20 project and released under GNU/GPL

i haven't made any change at all.



/*
* Tine 2.0
*
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @author Cornelius Weiss <c.weiss@metaways.de>
* @copyright Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
* @version $Id$
*
*/

Ext.namespace('Ext.ux', 'Ext.ux.layout');

/**
* @class Ext.ux.layout.HorizontalFitLayout
* @extends Ext.layout.ContainerLayout
* @description
* <p>This is a base class for layouts that contain a single item that automatically expands horizontally to fill
* the horizontal dimenson of the layout's container. This class is intended to be extended or created via the
* layout:'hfit' {@link Ext.Container#layout} config, and should generally not need to be created directly via
* the new keyword.</p>
* <p>To fit a panel to a container horizontally using Horizontal FitLayout, simply set layout:'hfit' on the container
* and add a multiple panel to it.</p>
* <p>Example usage:</p>
* <pre><code>
var p = new Ext.Panel({
title: 'Horizontal Fit Layout',
layout:'hfit',
items: [{
title: 'Inner Panel One',
html: '&lt;p&gt;This is the firsts inner panel content&lt;/p&gt;',
border: false
},{
title: 'Inner Panel Two',
html: '&lt;p&gt;This is the seconds inner panel content&lt;/p&gt;',
border: false
}]
});
</code></pre>
*/
Ext.ux.layout.HorizontalFitLayout = Ext.extend(Ext.layout.ContainerLayout, {
/**
* @cfg {bool} containsScrollbar
*/
containsScrollbar: false,
/**
* @private
*/
monitorResize:true,

/**
* @private
*/
onLayout : function(ct, target){
Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
if(!this.container.collapsed){
var size = target.getStyleSize();
size.width = ct.containsScrollbar ? size.width-16 : size.width;

ct.items.each(function(item){
this.setItemSize(item, size);
}, this);
}
},
/**
* @private
*/
setItemSize : function(item, size){
if(item && size.height > 0){ // display none?
item.setWidth(size.width);
}
}
});
Ext.Container.LAYOUTS['hfit'] = Ext.ux.layout.HorizontalFitLayout;




/*
* Tine 2.0
*
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @author Cornelius Weiss <c.weiss@metaways.de>
* @copyright Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
* @version $Id$
*
*/

Ext.namespace('Ext.ux', 'Ext.ux.form');

/**
* @class Ext.ux.form.ColumnFormPanel
* @description
* Helper Class for creating form panels with a horizontal layout. This class could be directly
* created using the new keyword or by specifying the xtype: 'columnform'
* Example usage:</p>
* <pre><code>
var p = new Ext.ux.form.ColumnFormPanel({
title: 'Horizontal Form Layout',
items: [
[
{
columnWidth: .6,
fieldLabel:'Company Name',
name:'org_name'
},
{
columnWidth: .4,
fieldLabel:'Street',
name:'adr_one_street'
}
],
[
{
columnWidth: .7,
fieldLabel:'Region',
name:'adr_one_region'
},
{
columnWidth: .3,
fieldLabel:'Postal Code',
name:'adr_one_postalcode'
}
]
]
});
</code></pre>
*/
Ext.ux.form.ColumnFormPanel = Ext.extend(Ext.Panel, {
/**
* @cfg
*/
formDefaults: {
xtype:'textfield',
anchor: '100%',
labelSeparator: '',
columnWidth: .333
},

layout: 'hfit',
labelAlign: 'top',
/**
* @private
*/
initComponent: function() {
var items = [];

// each item is an array with the config of one row
for (var i=0,j=this.items.length; i<j; i++) {

var initialRowConfig = this.items[i];
var rowConfig = {
border: false,
layout: 'column',
items: []
};
// each row consits n column objects
for (var n=0,m=initialRowConfig.length; n<m; n++) {
var column = initialRowConfig[n];
var idx = rowConfig.items.push({
columnWidth: column.columnWidth ? column.columnWidth : this.formDefaults.columnWidth,
layout: 'form',
labelAlign: this.labelAlign,
defaults: this.formDefaults,
bodyStyle: 'padding-right: 5px;',
border: false,
items: column
});

if (column.width) {
rowConfig.items[idx-1].width = column.width;
delete rowConfig.items[idx-1].columnWidth;
}
}
items.push(rowConfig);
}
this.items = items;

Ext.ux.form.ColumnFormPanel.superclass.initComponent.call(this);
}
});

Ext.reg('columnform', Ext.ux.form.ColumnFormPanel);


include them in this order and everything should be fine

Eric24
16 Nov 2009, 8:50 PM
There's one big problem I've encountered with this approach: The appended fields are added to the "parent" form during 'render'. That's great unless the form is hidden to start with and then made visible (and thus rendered) after the field values have been set/loaded. The appended fields aren't yet part of the hidden form, and so their values don't get set. I have not been able to come up with a solution for this. Any ideas?

frrogoy
5 Feb 2010, 5:00 AM
I'm using this version in 3.1. Thanks! I also found the helpText handy for creating a small spacer between groups of fields, when not using the inline items.

{
id: 'fconemail',
fieldLabel: 'Contact Email',
valueField: 'pocontemail',
helpText: '&nbsp;'
},...

col
20 Oct 2010, 3:31 AM
tnx man. Great plug.

chaitupash
4 Nov 2010, 7:46 AM
Cool man...........Great work...Thanks.

It is very useful...Cheers