2 * @class Ext.form.action.Submit
3 * @extends Ext.form.action.Action
4 * <p>A class which handles submission of data from {@link Ext.form.Basic Form}s
5 * and processes the returned response.</p>
6 * <p>Instances of this class are only created by a {@link Ext.form.Basic Form} when
7 * {@link Ext.form.Basic#submit submit}ting.</p>
8 * <p><u><b>Response Packet Criteria</b></u></p>
9 * <p>A response packet may contain:
10 * <div class="mdetail-params"><ul>
11 * <li><b><code>success</code></b> property : Boolean
12 * <div class="sub-desc">The <code>success</code> property is required.</div></li>
13 * <li><b><code>errors</code></b> property : Object
14 * <div class="sub-desc"><div class="sub-desc">The <code>errors</code> property,
15 * which is optional, contains error messages for invalid fields.</div></li>
17 * <p><u><b>JSON Packets</b></u></p>
18 * <p>By default, response packets are assumed to be JSON, so a typical response
19 * packet may look like this:</p><pre><code>
23 clientCode: "Client not found",
24 portOfLoading: "This field must not be null"
27 * <p>Other data may be placed into the response for processing by the {@link Ext.form.Basic}'s callback
28 * or event handler methods. The object decoded from this JSON is available in the
29 * {@link Ext.form.action.Action#result result} property.</p>
30 * <p>Alternatively, if an {@link #errorReader} is specified as an {@link Ext.data.reader.Xml XmlReader}:</p><pre><code>
31 errorReader: new Ext.data.reader.Xml({
39 * <p>then the results may be sent back in XML format:</p><pre><code>
40 <?xml version="1.0" encoding="UTF-8"?>
41 <message success="false">
44 <id>clientCode</id>
45 <msg><![CDATA[Code not found. <br /><i>This is a test validation message from the server </i>]]></msg>
48 <id>portOfLoading</id>
49 <msg><![CDATA[Port not found. <br /><i>This is a test validation message from the server </i>]]></msg>
54 * <p>Other elements may be placed into the response XML for processing by the {@link Ext.form.Basic}'s callback
55 * or event handler methods. The XML document is available in the {@link #errorReader}'s {@link Ext.data.reader.Xml#xmlData xmlData} property.</p>
57 Ext.define('Ext.form.action.Submit', {
58 extend:'Ext.form.action.Action',
59 alternateClassName: 'Ext.form.Action.Submit',
60 alias: 'formaction.submit',
65 * @cfg {boolean} clientValidation Determines whether a Form's fields are validated
66 * in a final call to {@link Ext.form.Basic#isValid isValid} prior to submission.
67 * Pass <tt>false</tt> in the Form's submit options to prevent this. Defaults to true.
73 if (this.clientValidation === false || form.isValid()) {
76 // client validation failed
77 this.failureType = Ext.form.action.Action.CLIENT_INVALID;
78 form.afterAction(this, false);
84 * Perform the submit of the form data.
86 doSubmit: function() {
88 ajaxOptions = Ext.apply(this.createCallback(), {
90 method: this.getMethod(),
94 // For uploads we need to create an actual form that contains the file upload fields,
95 // and pass that to the ajax call so it can do its iframe-based submit method.
96 if (this.form.hasUpload()) {
97 formEl = ajaxOptions.form = this.buildForm();
98 ajaxOptions.isUpload = true;
100 ajaxOptions.params = this.getParams();
103 Ext.Ajax.request(ajaxOptions);
106 Ext.removeNode(formEl);
112 * Build the full set of parameters from the field values plus any additional configured params.
114 getParams: function() {
116 configParams = this.callParent(),
117 fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
118 return Ext.apply({}, fieldParams, configParams);
123 * Build a form element containing fields corresponding to all the parameters to be
124 * submitted (everything returned by {@link #getParams}.
125 * NOTE: the form element is automatically added to the DOM, so any code that uses
126 * it must remove it from the DOM after finishing with it.
127 * @return HTMLFormElement
129 buildForm: function() {
133 basicForm = this.form,
134 params = this.getParams(),
137 basicForm.getFields().each(function(field) {
138 if (field.isFileUpload()) {
139 uploadFields.push(field);
143 function addField(name, val) {
152 // Add the form field values
153 Ext.iterate(params, function(key, val) {
154 if (Ext.isArray(val)) {
155 Ext.each(val, function(v) {
165 action: this.getUrl(),
166 method: this.getMethod(),
167 target: this.target || '_self',
168 style: 'display:none',
172 // Set the proper encoding for file uploads
173 if (uploadFields.length) {
174 formSpec.encoding = formSpec.enctype = 'multipart/form-data';
178 formEl = Ext.core.DomHelper.append(Ext.getBody(), formSpec);
180 // Special handling for file upload fields: since browser security measures prevent setting
181 // their values programatically, and prevent carrying their selected values over when cloning,
182 // we have to move the actual field instances out of their components and into the form.
183 Ext.Array.each(uploadFields, function(field) {
184 if (field.rendered) { // can only have a selected file value after being rendered
185 formEl.appendChild(field.extractFileInput());
197 onSuccess: function(response) {
198 var form = this.form,
200 result = this.processResponse(response);
201 if (result !== true && !result.success) {
203 form.markInvalid(result.errors);
205 this.failureType = Ext.form.action.Action.SERVER_INVALID;
208 form.afterAction(this, success);
214 handleResponse: function(response) {
215 var form = this.form,
216 errorReader = form.errorReader,
217 rs, errors, i, len, records;
219 rs = errorReader.read(response);
220 records = rs.records;
223 for(i = 0, len = records.length; i < len; i++) {
224 errors[i] = records[i].data;
227 if (errors.length < 1) {
231 success : rs.success,
235 return Ext.decode(response.responseText);