PDA

View Full Version : Form Enhancements (maxLength, defaulting combobox, + others)



DigitalSkyline
20 Feb 2008, 10:14 AM
The following override will apply the maxLength property to the textfield DOM element.




Ext.override(Ext.form.TextField, {
initComponent : function(){
if (this.maxLength!=Number.MAX_VALUE && !this.autoCreate) {
this.autoCreate = Ext.apply(this.getAutoCreate, {maxlength:this.maxLength});
}
Ext.form.TextField.superclass.initComponent.call(this);
this.addEvents(
'autosize'
);
}
});

DigitalSkyline
20 Feb 2008, 11:04 PM
A couple more bits...


Added MixedCollection of form fields.
Fields gain getForm() method
Fields can be managed using mapTo:
{
xtype:'textfield',
mapTo:'MyDataName' //no need for id/name property
}Some things that are not addressed, the allFields MixedCollection is not yet updated via add/remove methods but I'll probably add this in the future. I simply didn't need this functionality.




// Forms probably should not rely on ID/NAME for data population,
// in large applications this becomes unmanageable.

Ext.override(Ext.form.FormPanel, {
//We'll create a MixedCollection with references to each contained field
allFields : new Ext.util.MixedCollection(false, function(o){
return o.id || (o.id = Ext.id());
}),
afterRender : function(){
Ext.form.FormPanel.superclass.afterRender.call(this);
if (this.items) {
this.items.each(this.traverseFields, this);
}
},
traverseFields : function(f){
if(f.isFormField){
//add parent form reference
f.formId=this.getId();
//allFields will use mapTo, or name, for easy access.
this.allFields.add((f.mapTo||f.getName()),f);

} else {
if (f.items) {
//make recursive call
f.items.each(this.traverseFields, this);
}
}
}
});



Ext.override(Ext.form.Field, {

mapTo:'',
initComponent : function(){
//manage id's and name properties
if (this.mapTo) {
this.name = this.mapTo;
this.id = Ext.id(this.el,'managed-form');
}

Ext.form.Field.superclass.initComponent.call(this);
this.addEvents(
'focus',
'blur',
'specialkey',
'change',
'invalid',
'valid'
);

},
//give fields reference to the parent formPanel
getForm : function(){
if (this.formId) return Ext.getCmp(this.formId);
}
});

mystix
20 Feb 2008, 11:23 PM
you'll probably want to state somewhere though that the dom's maxLength property will render the TextField's maxLength config useless since the user will never be able to type past maxLength no. of characters.

DigitalSkyline
21 Feb 2008, 12:26 PM
Mystix, that's the whole point! :)

I don't know what the use case is of allowing typing beyond the character limit, I think the browser's behavior is what is expected in 99% of the cases out there (who knows maybe there is a 1% reason to allow it?)

In any case as you point out, and to anyone that this is not obvious to, the override in the first post will make the ~2 pieces of code in Ext that detects maxLength for validation, redundant.

For those who want the browser's behavior, this matters naught. For those who want the Ext behavior of allowing typing beyond the limit, but to simply invalidate the field, need not apply.

I supply this fix for those that need it; for those users who expected the browser's behavior (I think that's probably quite a few people).

Cheers!

jerrybrown5
24 Feb 2008, 9:10 PM
I guess it is a matter of preference. For me I think the ideal use case is to have a combination of the two. While keystrokes are being entered that exceed the maximum length, the best case it to hover a validation message for a second or two. In that case you would probably trap the keydown, but you will still need the normal validation message in the event that it was bypassed by a cut and paste action.

Btw, I don't intend on causing any rioting or the sort but is anyone else sick of having to validate every field two or three times between the client and server interaction?

DigitalSkyline
28 Feb 2008, 9:44 AM
Another override for presetting combobox values loaded from JSON via nested object. This override allows you to preset a combobox without loading its entire store.

Thanks to milanz for original code, while it didn't work for me, it pointed me in the right direction. Original post: http://extjs.com/forum/showthread.php?t=20803

Example JSON:
{sucess:true, items:{normalfield:'normalvalue', mycombo:{value:'..', display:'...'}}

Improvements are welcome!




Ext.override(Ext.form.BasicForm, {
setValues : function(values){
var v, f, d;
if(Ext.isArray(values)){ // array of objects
for(var i = 0, len = values.length; i < len; i++){
v = values[i];
f = this.findField(v.id);
if(f){
if(typeof v == 'object' && f.mode == 'remote'){
d = v[f.displayField];
v = v[f.valueField];
} else {
v = v.value;
d = v; //default
}
if (f.getXType()=='combo'){
f.lastSelectionText = d;
if (f.hiddenField) {
f.hiddenField.value = v;
}
Ext.form.ComboBox.superclass.setValue.call(f, d);
f.value = v;
}else{
f.setValue(v);
}

if(this.trackResetOnLoad){
f.originalValue = f.getValue();
}
}
}
}else{ // object hash
var id;
for(id in values){
v = values[id];
if(typeof v != 'function' && (f = this.findField(id))){
if(typeof v == 'object' && f.mode == 'remote'){
d = v[f.displayField];
v = v[f.valueField];
} else {
d = v; //default
}
if (f.getXType()=='combo'){
f.lastSelectionText = d;
if (f.hiddenField) {
f.hiddenField.value = v;
}
Ext.form.ComboBox.superclass.setValue.call(f, d);
f.value = v;
} else {
f.setValue(v);
}

if(this.trackResetOnLoad){
f.originalValue = f.getValue();
}
}
}
}
return this;
}

});

milanz
28 Feb 2008, 11:17 AM
Thanks to milanz for original code, while it didn't work for me, it pointed me in the right direction. Original post:


It probably didn't work because I was using Ext v1.02 and posted the code in a v.2 topic area. 8-|

DigitalSkyline, absolutely brilliant -- thanks for taking the time to make improvements.

dearsina
29 Feb 2008, 4:53 AM
How different would this be for XML loads?

DigitalSkyline
29 Feb 2008, 5:48 AM
As far as I'm aware there really should not be a difference, as long as your using a standard Ext.record to populate the form. The record object supplied to the form should be the same.

However the built in form action.Load requires a JSON result, with a success property.