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 Ext.form.Basic#errorReader 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 Ext.form.Basic#errorReader errorReader}'s
70 * {@link Ext.data.reader.Xml#xmlData xmlData} property.</p>
72 Ext.define('Ext.form.action.Submit', {
73 extend:'Ext.form.action.Action',
74 alternateClassName: 'Ext.form.Action.Submit',
75 alias: 'formaction.submit',
80 * @cfg {Boolean} clientValidation Determines whether a Form's fields are validated
81 * in a final call to {@link Ext.form.Basic#isValid isValid} prior to submission.
82 * Pass <tt>false</tt> in the Form's submit options to prevent this. Defaults to true.
88 if (this.clientValidation === false || form.isValid()) {
91 // client validation failed
92 this.failureType = Ext.form.action.Action.CLIENT_INVALID;
93 form.afterAction(this, false);
99 * Perform the submit of the form data.
101 doSubmit: function() {
103 ajaxOptions = Ext.apply(this.createCallback(), {
105 method: this.getMethod(),
106 headers: this.headers
109 // For uploads we need to create an actual form that contains the file upload fields,
110 // and pass that to the ajax call so it can do its iframe-based submit method.
111 if (this.form.hasUpload()) {
112 formEl = ajaxOptions.form = this.buildForm();
113 ajaxOptions.isUpload = true;
115 ajaxOptions.params = this.getParams();
118 Ext.Ajax.request(ajaxOptions);
121 Ext.removeNode(formEl);
127 * Build the full set of parameters from the field values plus any additional configured params.
129 getParams: function() {
131 configParams = this.callParent(),
132 fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
133 return Ext.apply({}, fieldParams, configParams);
138 * Build a form element containing fields corresponding to all the parameters to be
139 * submitted (everything returned by {@link #getParams}.
140 * NOTE: the form element is automatically added to the DOM, so any code that uses
141 * it must remove it from the DOM after finishing with it.
142 * @return HTMLFormElement
144 buildForm: function() {
148 basicForm = this.form,
149 params = this.getParams(),
152 basicForm.getFields().each(function(field) {
153 if (field.isFileUpload()) {
154 uploadFields.push(field);
158 function addField(name, val) {
163 value: Ext.String.htmlEncode(val)
167 // Add the form field values
168 Ext.iterate(params, function(key, val) {
169 if (Ext.isArray(val)) {
170 Ext.each(val, function(v) {
180 action: this.getUrl(),
181 method: this.getMethod(),
182 target: this.target || '_self',
183 style: 'display:none',
187 // Set the proper encoding for file uploads
188 if (uploadFields.length) {
189 formSpec.encoding = formSpec.enctype = 'multipart/form-data';
193 formEl = Ext.DomHelper.append(Ext.getBody(), formSpec);
195 // Special handling for file upload fields: since browser security measures prevent setting
196 // their values programatically, and prevent carrying their selected values over when cloning,
197 // we have to move the actual field instances out of their components and into the form.
198 Ext.Array.each(uploadFields, function(field) {
199 if (field.rendered) { // can only have a selected file value after being rendered
200 formEl.appendChild(field.extractFileInput());
212 onSuccess: function(response) {
213 var form = this.form,
215 result = this.processResponse(response);
216 if (result !== true && !result.success) {
218 form.markInvalid(result.errors);
220 this.failureType = Ext.form.action.Action.SERVER_INVALID;
223 form.afterAction(this, success);
229 handleResponse: function(response) {
230 var form = this.form,
231 errorReader = form.errorReader,
232 rs, errors, i, len, records;
234 rs = errorReader.read(response);
235 records = rs.records;
238 for(i = 0, len = records.length; i < len; i++) {
239 errors[i] = records[i].data;
242 if (errors.length < 1) {
246 success : rs.success,
250 return Ext.decode(response.responseText);