3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.form.action.Submit
17 * @extends Ext.form.action.Action
18 * <p>A class which handles submission of data from {@link Ext.form.Basic Form}s
19 * and processes the returned response.</p>
20 * <p>Instances of this class are only created by a {@link Ext.form.Basic Form} when
21 * {@link Ext.form.Basic#submit submit}ting.</p>
22 * <p><u><b>Response Packet Criteria</b></u></p>
23 * <p>A response packet may contain:
24 * <div class="mdetail-params"><ul>
25 * <li><b><code>success</code></b> property : Boolean
26 * <div class="sub-desc">The <code>success</code> property is required.</div></li>
27 * <li><b><code>errors</code></b> property : Object
28 * <div class="sub-desc"><div class="sub-desc">The <code>errors</code> property,
29 * which is optional, contains error messages for invalid fields.</div></li>
31 * <p><u><b>JSON Packets</b></u></p>
32 * <p>By default, response packets are assumed to be JSON, so a typical response
33 * packet may look like this:</p><pre><code>
37 clientCode: "Client not found",
38 portOfLoading: "This field must not be null"
41 * <p>Other data may be placed into the response for processing by the {@link Ext.form.Basic}'s callback
42 * or event handler methods. The object decoded from this JSON is available in the
43 * {@link Ext.form.action.Action#result result} property.</p>
44 * <p>Alternatively, if an {@link #errorReader} is specified as an {@link Ext.data.reader.Xml XmlReader}:</p><pre><code>
45 errorReader: new Ext.data.reader.Xml({
53 * <p>then the results may be sent back in XML format:</p><pre><code>
54 <?xml version="1.0" encoding="UTF-8"?>
55 <message success="false">
58 <id>clientCode</id>
59 <msg><![CDATA[Code not found. <br /><i>This is a test validation message from the server </i>]]></msg>
62 <id>portOfLoading</id>
63 <msg><![CDATA[Port not found. <br /><i>This is a test validation message from the server </i>]]></msg>
68 * <p>Other elements may be placed into the response XML for processing by the {@link Ext.form.Basic}'s callback
69 * or event handler methods. The XML document is available in the {@link #errorReader}'s {@link Ext.data.reader.Xml#xmlData xmlData} property.</p>
71 Ext.define('Ext.form.action.Submit', {
72 extend:'Ext.form.action.Action',
73 alternateClassName: 'Ext.form.Action.Submit',
74 alias: 'formaction.submit',
79 * @cfg {boolean} clientValidation Determines whether a Form's fields are validated
80 * in a final call to {@link Ext.form.Basic#isValid isValid} prior to submission.
81 * Pass <tt>false</tt> in the Form's submit options to prevent this. Defaults to true.
87 if (this.clientValidation === false || form.isValid()) {
90 // client validation failed
91 this.failureType = Ext.form.action.Action.CLIENT_INVALID;
92 form.afterAction(this, false);
98 * Perform the submit of the form data.
100 doSubmit: function() {
102 ajaxOptions = Ext.apply(this.createCallback(), {
104 method: this.getMethod(),
105 headers: this.headers
108 // For uploads we need to create an actual form that contains the file upload fields,
109 // and pass that to the ajax call so it can do its iframe-based submit method.
110 if (this.form.hasUpload()) {
111 formEl = ajaxOptions.form = this.buildForm();
112 ajaxOptions.isUpload = true;
114 ajaxOptions.params = this.getParams();
117 Ext.Ajax.request(ajaxOptions);
120 Ext.removeNode(formEl);
126 * Build the full set of parameters from the field values plus any additional configured params.
128 getParams: function() {
130 configParams = this.callParent(),
131 fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
132 return Ext.apply({}, fieldParams, configParams);
137 * Build a form element containing fields corresponding to all the parameters to be
138 * submitted (everything returned by {@link #getParams}.
139 * NOTE: the form element is automatically added to the DOM, so any code that uses
140 * it must remove it from the DOM after finishing with it.
141 * @return HTMLFormElement
143 buildForm: function() {
147 basicForm = this.form,
148 params = this.getParams(),
151 basicForm.getFields().each(function(field) {
152 if (field.isFileUpload()) {
153 uploadFields.push(field);
157 function addField(name, val) {
162 value: Ext.String.htmlEncode(val)
166 // Add the form field values
167 Ext.iterate(params, function(key, val) {
168 if (Ext.isArray(val)) {
169 Ext.each(val, function(v) {
179 action: this.getUrl(),
180 method: this.getMethod(),
181 target: this.target || '_self',
182 style: 'display:none',
186 // Set the proper encoding for file uploads
187 if (uploadFields.length) {
188 formSpec.encoding = formSpec.enctype = 'multipart/form-data';
192 formEl = Ext.core.DomHelper.append(Ext.getBody(), formSpec);
194 // Special handling for file upload fields: since browser security measures prevent setting
195 // their values programatically, and prevent carrying their selected values over when cloning,
196 // we have to move the actual field instances out of their components and into the form.
197 Ext.Array.each(uploadFields, function(field) {
198 if (field.rendered) { // can only have a selected file value after being rendered
199 formEl.appendChild(field.extractFileInput());
211 onSuccess: function(response) {
212 var form = this.form,
214 result = this.processResponse(response);
215 if (result !== true && !result.success) {
217 form.markInvalid(result.errors);
219 this.failureType = Ext.form.action.Action.SERVER_INVALID;
222 form.afterAction(this, success);
228 handleResponse: function(response) {
229 var form = this.form,
230 errorReader = form.errorReader,
231 rs, errors, i, len, records;
233 rs = errorReader.read(response);
234 records = rs.records;
237 for(i = 0, len = records.length; i < len; i++) {
238 errors[i] = records[i].data;
241 if (errors.length < 1) {
245 success : rs.success,
249 return Ext.decode(response.responseText);