How to submit Ext forms the right way
Updated 2008/03/12: The code got updated, read more at the bottom.
When you work with Ext, sooner or later you will stumble across a design desicion made by the ext developers: Submitting forms is done in the traditional way. This means that the values submitted come from the value field of the input-tag inside the form. This leads to several problems:
- Checkboxes which are not checked are not submitted at all (as normal html-forms also do)
- Comboboxes get their displayed value submitted, and not the value behind the combobox
- DateFields get their displayed date submitted, which may be different based on the users locale
- All Formitems which return something different in their getValue() method from what is written inside the input tags value attribute will probably not be submitted correctly.
Thankfully, after some pondering, I developed a nice solution: OOSubmit!
OOSubmit is a custom Ext.form.Action which submits forms in an object-oriented way. - Hence the name OOSubmit. Instead of going trough the forms input-elements and getting their value attributes, this submit action goes through the form items and calls their corresponding getValue() method. It also looks if the item has a getSubmitValue() method and used that instead of getValue() if present.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | Ext.namespace("Ext.ux"); /** * This submit action is basically the same as the normal submit action, * only that it uses the fields getSubmitValue() to compose the values to submit, * instead of looping over the input-tags in the form-tag of the form. * * To use it, just use the OOSubmit-plugin on either a FormPanel or a BasicForm, * or explicitly call form.doAction('oosubmit'); * * @param {Object} form * @param {Object} options */ Ext.ux.OOSubmitAction = function(form, options){ Ext.ux.OOSubmitAction.superclass.constructor.call(this, form, options); }; Ext.extend(Ext.ux.OOSubmitAction, Ext.form.Action.Submit, { /** * @cfg {boolean} clientValidation Determines whether a Form's fields are validated * in a final call to {@link Ext.form.BasicForm#isValid isValid} prior to submission. * Pass <tt>false</tt> in the Form's submit options to prevent this. If not defined, pre-submission field validation * is performed. */ type : 'oosubmit', // private /** * This is nearly a copy of the original submit action run method */ run : function(){ var o = this.options; var method = this.getMethod(); var isPost = method == 'POST'; var params = this.options.params || {}; if (isPost) Ext.applyIf(params, this.form.baseParams); //now add the form parameters this.form.items.each(function(field) { if (!field.disabled) { //check if the form item provides a specialized getSubmitValue() and use that if available if (typeof field.getSubmitValue == "function") params[field.getName()] = field.getSubmitValue(); else params[field.getName()] = field.getValue(); } }); //convert params to get style if we are not post if (!isPost) params=Ext.urlEncode(params); if(o.clientValidation === false || this.form.isValid()){ Ext.Ajax.request(Ext.apply(this.createCallback(o), { url:this.getUrl(!isPost), method: method, params:params, //add our values isUpload: this.form.fileUpload })); }else if (o.clientValidation !== false){ // client validation failed this.failureType = Ext.form.Action.CLIENT_INVALID; this.form.afterAction(this, false); } }, }); //add our action to the registry of known actions Ext.form.Action.ACTION_TYPES['oosubmit'] = Ext.ux.OOSubmitAction; |
To use this, simply include the code somewhere in your page, and when you want to submit the form dont use form.submit() but form.doAction(’oosubmit’); This way you may always submit the form in the traditional way.
To make it even easier, i wrote a small plugin which can be plugged into a BasicForm or FormPanel. It overrides the standard submit() action and uses the OOSubmit action by default.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /** * This plugin can be either used on BasicForm or FormPanel. * In both cases it changes the behaviour of submit() to use * the 'oosubmit' action instead of the 'submit' action. */ Ext.ux.OOSubmit=function() { this.init=function(_object) { var form=null; if (typeof _object.form=="object") { //we are a formpanel: form=_object.form; } else form=_object; //Save the old submit method: form.oldSubmit=form.submit; //create a new submit method which calls the oosubmit action per default: form.submit=function(options) { this.doAction('oosubmit', options); return this; }; }; }; |
To use the plugin, simply constuct a BasicForm or FormPanel and add this to the config:
- Done.
The checkbox problem and the combobox gets solved by OOSubmit automatically, because the getValue() function is used.
To fix the datetime problem mentioned above I spent Ext.form.DateField a getSubmitValue() function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * Returns the submit value of the datefield, always in the same format, * regardless of display format. * The format returned is Y-m-d, because this is common format used in rdbms. (mysql for example) * */ Ext.form.DateField.prototype.getSubmitValue=function() { var v = this.getValue(); if(v !=='') { var date= new Date(v); return date.format("Y-m-d"); } return v; }; |
Thats it! Now everything works like it should (IMHO).
Questions, ideas for improvements, bugs?
Update on 2008/03/12:
OOSubmit now also supports baseParams of forms in POST and GET mode, also custom params passed to form.doAction() are now honored.
As mentioned in the ext forums, the code will now discard disabled fields and not submit them as normal.
The bugs mentioned in the comments have also been fixed. The code should now work out of the box.



there’s a bug in the run method:
typeof file.getSubmitValue
should be
typeof field.getSubmitValue