]>
git.proxmox.com Git - sencha-touch.git/blob - src/src/form/Panel.js
2 * The Form panel presents a set of form fields and provides convenient ways to load and save data. Usually a form
3 * panel just contains the set of fields you want to display, ordered inside the items configuration like this:
6 * var form = Ext.create('Ext.form.Panel', {
15 * xtype: 'emailfield',
20 * xtype: 'passwordfield',
27 * Here we just created a simple form panel which could be used as a registration form to sign up to your service. We
28 * added a plain {@link Ext.field.Text text field} for the user's Name, an {@link Ext.field.Email email field} and
29 * finally a {@link Ext.field.Password password field}. In each case we provided a {@link Ext.field.Field#name name}
30 * config on the field so that we can identify it later on when we load and save data on the form.
34 * Using the form we created above, we can load data into it in a few different ways, the easiest is to use
39 * email: 'ed@sencha.com',
43 * It's also easy to load {@link Ext.data.Model Model} instances into a form - let's say we have a User model and want
44 * to load a particular instance into our form:
46 * Ext.define('MyApp.model.User', {
47 * extend: 'Ext.data.Model',
49 * fields: ['name', 'email', 'password']
53 * var ed = Ext.create('MyApp.model.User', {
55 * email: 'ed@sencha.com',
61 * ##Retrieving form data
63 * Getting data out of the form panel is simple and is usually achieve via the {@link #getValues} method:
65 * var values = form.getValues();
67 * //values now looks like this:
70 * email: 'ed@sencha.com',
74 * It's also possible to listen to the change events on individual fields to get more timely notification of changes
75 * that the user is making. Here we expand on the example above with the User model, updating the model as soon as
76 * any of the fields are changed:
78 * var form = Ext.create('Ext.form.Panel', {
81 * change: function(field, newValue, oldValue) {
82 * ed.set(field.getName(), newValue);
93 * xtype: 'emailfield',
98 * xtype: 'passwordfield',
105 * The above used a new capability of Sencha Touch 2.0, which enables you to specify listeners on child components of any
106 * container. In this case, we attached a listener to the {@link Ext.field.Text#change change} event of each form
107 * field that is a direct child of the form panel. Our listener gets the name of the field that fired the change event,
108 * and updates our {@link Ext.data.Model Model} instance with the new value. For example, changing the email field
109 * in the form will update the Model's email field.
113 * There are a few ways to submit form data. In our example above we have a Model instance that we have updated, giving
114 * us the option to use the Model's {@link Ext.data.Model#save save} method to persist the changes back to our server,
115 * without using a traditional form submission. Alternatively, we can send a normal browser form submit using the
116 * {@link #method} method:
119 * url: 'url/to/submit/to',
121 * success: function() {
122 * alert('form submitted successfully!');
126 * In this case we provided the `url` to submit the form to inside the submit call - alternatively you can just set the
127 * {@link #url} configuration when you create the form. We can specify other parameters (see {@link #method} for a
128 * full list), including callback functions for success and failure, which are called depending on whether or not the
129 * form submission was successful. These functions are usually used to take some action in your app after your data
130 * has been saved to the server side.
132 * For more information regarding forms and fields, please review [Using Forms in Sencha Touch Guide](../../../components/forms.html)
134 Ext
.define('Ext.form.Panel', {
135 alternateClassName
: 'Ext.form.FormPanel',
136 extend
: 'Ext.Panel',
138 requires
: ['Ext.XTemplate', 'Ext.field.Checkbox', 'Ext.Ajax'],
142 * @preventable doSubmit
143 * Fires upon successful (Ajax-based) form submission.
144 * @param {Ext.form.Panel} this This FormPanel.
145 * @param {Object} result The result object as returned by the server.
146 * @param {Ext.EventObject} e The event object.
150 * @event beforesubmit
151 * @preventable doBeforeSubmit
152 * Fires immediately preceding any Form submit action.
153 * Implementations may adjust submitted form values or options prior to execution.
154 * A return value of `false` from this listener will abort the submission
155 * attempt (regardless of `standardSubmit` configuration).
156 * @param {Ext.form.Panel} this This FormPanel.
157 * @param {Object} values A hash collection of the qualified form values about to be submitted.
158 * @param {Object} options Submission options hash (only available when `standardSubmit` is `false`).
159 * @param {Ext.EventObject} e The event object if the form was submitted via a HTML5 form submit event.
164 * Fires when either the Ajax HTTP request reports a failure OR the server returns a `success:false`
165 * response in the result payload.
166 * @param {Ext.form.Panel} this This FormPanel.
167 * @param {Object} result Either a failed Ext.data.Connection request object or a failed (logical) server.
173 * @cfg {String} baseCls
176 baseCls
: Ext
.baseCSSPrefix
+ 'form',
179 * @cfg {Boolean} standardSubmit
180 * Whether or not we want to perform a standard form submit.
183 standardSubmit
: false,
187 * The default url for submit actions.
193 * @cfg (String} enctype
194 * The enctype attribute for the form, specifies how the form should be encoded when submitting
199 * @cfg {Object} baseParams
200 * Optional hash of params to be sent (when `standardSubmit` configuration is `false`) on every submit.
206 * @cfg {Object} submitOnAction
207 * When this is set to `true`, the form will automatically submit itself whenever the `action`
208 * event fires on a field in this form. The action event usually fires whenever you press
209 * go or enter inside a textfield.
212 submitOnAction
: false,
215 * @cfg {Ext.data.Model} record The model instance of this form. Can by dynamically set at any time.
221 * @cfg {String} method
222 * The method which this form will be submitted. `post` or `get`.
227 * @cfg {Object} scrollable
228 * Possible values are true, false, and null. The true value indicates that
229 * users can scroll the panel. The false value disables scrolling, but developers
230 * can enable it in the app. The null value indicates that the object cannot be
231 * scrolled and that scrolling cannot be enabled for this object.
235 * xtype: 'formpanel',
236 * iconCls: Ext.filterPlatform('blackberry') ? 'list' : null,
243 translationMethod
: 'scrollposition'
248 * @cfg {Boolean} trackResetOnLoad
249 * If set to true, {@link #reset}() resets to the last loaded or {@link #setValues}() data instead of
250 * when the form was first created.
252 trackResetOnLoad
:false,
256 * If specified, load and submit actions will be loaded and submitted via Ext.Direct. Methods which have been imported by
257 * {@link Ext.direct.Manager} can be specified here to load and submit forms. API methods may also be
258 * specified as strings and will be parsed into the actual functions when the first submit or load has occurred. Such as the following:
261 * load: App.ss.MyProfile.load,
262 * submit: App.ss.MyProfile.submit
266 * load: 'App.ss.MyProfile.load',
267 * submit: 'App.ss.MyProfile.submit'
270 * Load actions can use {@link #paramOrder} or {@link #paramsAsHash} to customize how the load method
271 * is invoked. Submit actions will always use a standard form submit. The `formHandler` configuration
272 * (see Ext.direct.RemotingProvider#action) must be set on the associated server-side method which has
273 * been imported by {@link Ext.direct.Manager}.
278 * @cfg {String/String[]} paramOrder
279 * A list of params to be executed server side. Only used for the {@link #api} `load`
282 * Specify the params in the order in which they must be executed on the
283 * server-side as either (1) an Array of String values, or (2) a String of params
284 * delimited by either whitespace, comma, or pipe. For example,
285 * any of the following would be acceptable:
287 * paramOrder: ['param1','param2','param3']
288 * paramOrder: 'param1 param2 param3'
289 * paramOrder: 'param1,param2,param3'
290 * paramOrder: 'param1|param2|param'
295 * @cfg {Boolean} paramsAsHash
296 * Only used for the {@link #api} `load` configuration. If true, parameters will be sent as a
297 * single hash collection of named arguments. Providing a {@link #paramOrder} nullifies this
303 * @cfg {Number} timeout
304 * Timeout for form actions in seconds.
309 * @cfg {Boolean} multipartDetection
310 * If this is enabled the form will automatically detect the need to use 'multipart/form-data' during submission.
312 multipartDetection
: true,
315 * @cfg {Boolean} enableSubmissionForm
316 * The submission form is generated but never added to the dom. It is a submittable version of your form panel, allowing for fields
317 * that are not simple textfields to be properly submitted to servers. It will also send values that are easier to parse
318 * with server side code.
320 * If this is false we will attempt to subject the raw form inside the form panel.
322 enableSubmissionForm
: true
325 getElementConfig: function() {
326 var config
= this.callParent();
328 // Added a submit input for standard form submission. This cannot have "display: none;" or it will not work
329 config
.children
.push({
332 style
: 'visibility: hidden; width: 0; height: 0; position: absolute; right: 0; bottom: 0;'
339 initialize: function() {
349 applyEnctype: function(newValue
) {
350 var form
= this.element
.dom
|| null;
353 form
.setAttribute("enctype", newValue
);
355 form
.setAttribute("enctype");
360 updateRecord: function(newRecord
) {
361 var fields
, values
, name
;
363 if (newRecord
&& (fields
= newRecord
.fields
)) {
364 values
= this.getValues();
365 for (name
in values
) {
366 if (values
.hasOwnProperty(name
) && fields
.containsKey(name
)) {
367 newRecord
.set(name
, values
[name
]);
375 * Loads matching fields from a model instance into this form.
376 * @param {Ext.data.Model} record The model instance.
377 * @return {Ext.form.Panel} This form.
379 setRecord: function(record
) {
382 if (record
&& record
.data
) {
383 me
.setValues(record
.data
);
392 onSubmit: function(e
) {
394 if (e
&& !me
.getStandardSubmit()) {
397 // Stop the submit event on the original for if we are swapping a form in
398 if (me
.getEnableSubmissionForm()) {
401 this.submit(null, e
);
405 updateSubmitOnAction: function(newSubmitOnAction
) {
406 if (newSubmitOnAction
) {
408 action
: 'onFieldAction',
413 action
: 'onFieldAction',
420 onFieldAction: function(field
) {
421 if (this.getSubmitOnAction()) {
428 * Performs a Ajax-based submission of form values (if {@link #standardSubmit} is false) or otherwise
429 * executes a standard HTML Form submit action.
433 * 1. Only the first parameter is implemented. Put all other parameters inside the first
436 * submit({params: "" ,headers: "" etc.})
441 * url: 'PostMyData/To',
443 * success: function() { Ext.Msg.alert("success"); },
444 * failure: function() { Ext.Msg.alert("error"); }
447 * 3. Parameters and values only submit for a POST and not for a GET.
449 * @param {Object} options
450 * The configuration when submitting this form.
452 * The following are the configurations when submitting via Ajax only:
454 * @param {String} options.url
455 * The url for the action (defaults to the form's {@link #url}).
457 * @param {String} options.method
458 * The form method to use (defaults to the form's {@link #method}, or POST if not defined).
460 * @param {Object} options.headers
461 * Request headers to set for the action.
463 * @param {Boolean} [options.autoAbort=false]
464 * `true` to abort any pending Ajax request prior to submission.
465 * __Note:__ Has no effect when `{@link #standardSubmit}` is enabled.
467 * @param {Number} options.timeout
468 * The number is seconds the loading will timeout in.
470 * The following are the configurations when loading via Ajax or Direct:
472 * @param {String/Object} options.params
473 * The params to pass when submitting this form (defaults to this forms {@link #baseParams}).
474 * Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.
476 * @param {Boolean} [options.submitDisabled=false]
477 * `true` to submit all fields regardless of disabled state.
478 * __Note:__ Has no effect when `{@link #standardSubmit}` is enabled.
480 * @param {String/Object} [options.waitMsg]
481 * If specified, the value which is passed to the loading {@link #masked mask}. See {@link #masked} for
484 * @param {Function} options.success
485 * The callback that will be invoked after a successful response. A response is successful if
486 * a response is received from the server and is a JSON object where the `success` property is set
487 * to `true`, `{"success": true}`.
489 * The function is passed the following parameters and can be used for submitting via Ajax or Direct:
491 * @param {Ext.form.Panel} options.success.form
492 * The {@link Ext.form.Panel} that requested the action.
494 * @param {Object/Ext.direct.Event} options.success.result
495 * The result object returned by the server as a result of the submit request. If the submit is sent using Ext.Direct,
496 * this will return the {@link Ext.direct.Event} instance, otherwise will return an Object.
498 * @param {Object} options.success.data
499 * The parsed data returned by the server.
501 * @param {Function} options.failure
502 * The callback that will be invoked after a failed transaction attempt.
504 * The function is passed the following parameters and can be used for submitting via Ajax or Direct:
506 * @param {Ext.form.Panel} options.failure.form
507 * The {@link Ext.form.Panel} that requested the submit.
509 * @param {Ext.form.Panel} options.failure.result
510 * The failed response or result object returned by the server which performed the operation.
512 * @param {Object} options.success.data
513 * The parsed data returned by the server.
515 * @param {Object} options.scope
516 * The scope in which to call the callback functions (The `this` reference for the callback functions).
518 * @return {Ext.data.Connection} The request object if the {@link #standardSubmit} config is false.
519 * If the standardSubmit config is true, then the return value is undefined.
521 submit: function(options
, e
) {
522 options
= options
|| {};
525 formValues
= me
.getValues(me
.getStandardSubmit() || !options
.submitDisabled
),
526 form
= me
.element
.dom
|| {};
528 if(this.getEnableSubmissionForm()) {
529 form
= this.createSubmissionForm(form
, formValues
);
532 options
= Ext
.apply({
533 url
: me
.getUrl() || form
.action
,
536 method
: me
.getMethod() || form
.method
|| 'post',
545 return me
.fireAction('beforesubmit', [me
, formValues
, options
, e
], 'doBeforeSubmit');
548 createSubmissionForm: function(form
, values
) {
549 var fields
= this.getFields(),
550 name
, input
, field
, fileinputElement
, inputComponent
;
552 if(form
.nodeType
=== 1) {
553 form
= form
.cloneNode(false);
555 for (name
in values
) {
556 input
= document
.createElement("input");
557 input
.setAttribute("type", "text");
558 input
.setAttribute("name", name
);
559 input
.setAttribute("value", values
[name
]);
560 form
.appendChild(input
);
564 for (name
in fields
) {
565 if (fields
.hasOwnProperty(name
)) {
566 field
= fields
[name
];
568 if(!form
.$fileswap
) form
.$fileswap
= [];
570 inputComponent
= field
.getComponent().input
;
571 fileinputElement
= inputComponent
.dom
;
572 input
= fileinputElement
.cloneNode(true);
573 fileinputElement
.parentNode
.insertBefore(input
, fileinputElement
.nextSibling
);
574 form
.appendChild(fileinputElement
);
575 form
.$fileswap
.push({original
: fileinputElement
, placeholder
: input
});
576 } else if(field
.isPassword
) {
577 if(field
.getComponent().getType
!== "password") {
578 field
.setRevealed(false);
587 doBeforeSubmit: function(me
, formValues
, options
) {
588 var form
= options
.form
|| {},
589 multipartDetected
= false;
591 if(this.getMultipartDetection() === true) {
592 this.getFieldsAsArray().forEach(function(field
) {
593 if(field
.isFile
=== true) {
594 multipartDetected
= true;
599 if(multipartDetected
) {
600 form
.setAttribute("enctype", "multipart/form-data");
604 if(options
.enctype
) {
605 form
.setAttribute("enctype", options
.enctype
);
608 if (me
.getStandardSubmit()) {
609 if (options
.url
&& Ext
.isEmpty(form
.action
)) {
610 form
.action
= options
.url
;
613 // Spinner fields must have their components enabled *before* submitting or else the value
614 // will not be posted.
615 var fields
= this.query('spinnerfield'),
619 for (i
= 0; i
< ln
; i
++) {
621 if (!field
.getDisabled()) {
622 field
.getComponent().setDisabled(false);
626 form
.method
= (options
.method
|| form
.method
).toLowerCase();
629 var api
= me
.getApi(),
630 url
= options
.url
|| me
.getUrl(),
631 scope
= options
.scope
|| me
,
632 waitMsg
= options
.waitMsg
,
633 failureFn = function(response
, responseText
) {
634 if (Ext
.isFunction(options
.failure
)) {
635 options
.failure
.call(scope
, me
, response
, responseText
);
638 me
.fireEvent('exception', me
, response
);
640 successFn = function(response
, responseText
) {
641 if (Ext
.isFunction(options
.success
)) {
642 options
.success
.call(options
.scope
|| me
, me
, response
, responseText
);
645 me
.fireEvent('submit', me
, response
);
649 if (options
.waitMsg
) {
650 if (typeof waitMsg
=== 'string') {
657 me
.setMasked(waitMsg
);
663 if (typeof submit
=== 'string') {
664 submit
= Ext
.direct
.Manager
.parseMethod(submit
);
672 return submit(this.element
, function(data
, response
, success
) {
677 successFn(response
, data
);
679 failureFn(response
, data
);
682 failureFn(response
, data
);
687 var request
= Ext
.merge({},
690 timeout
: this.getTimeout() * 1000,
696 delete request
.success
;
697 delete request
.failure
;
699 request
.params
= Ext
.merge(me
.getBaseParams() || {}, options
.params
);
700 request
.header
= Ext
.apply(
702 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
704 options
.headers
|| {}
706 request
.callback = function(callbackOptions
, success
, response
) {
707 var responseText
= response
.responseText
,
708 responseXML
= response
.responseXML
,
709 statusResult
= Ext
.Ajax
.parseStatus(response
.status
, response
);
712 var original
, placeholder
;
713 Ext
.each(form
.$fileswap
, function(item
) {
714 original
= item
.original
;
715 placeholder
= item
.placeholder
;
717 placeholder
.parentNode
.insertBefore(original
, placeholder
.nextSibling
);
718 placeholder
.parentNode
.removeChild(placeholder
);
720 form
.$fileswap
= null;
721 delete form
.$fileswap
;
726 if(response
.success
=== false) success
= false;
728 if (statusResult
&& responseText
&& responseText
.length
== 0) {
731 if(!Ext
.isEmpty(response
.responseBytes
)) {
732 success
= statusResult
.success
;
734 if(Ext
.isString(responseText
) && response
.request
.options
.responseType
=== "text") {
735 response
.success
= true;
736 } else if(Ext
.isString(responseText
)) {
738 response
= Ext
.decode(responseText
);
740 response
.success
= false;
742 response
.message
= e
.message
;
744 } else if(Ext
.isSimpleObject(responseText
)) {
745 response
= responseText
;
746 Ext
.applyIf(response
, {success
:true});
749 if(!Ext
.isEmpty(responseXML
)){
750 response
.success
= true;
752 success
= !!response
.success
;
756 successFn(response
, responseText
);
758 failureFn(response
, responseText
);
762 failureFn(response
, responseText
);
766 if(Ext
.feature
.has
.XHR2
&& request
.xhr2
) {
768 var formData
= new FormData(form
);
769 if (request
.params
) {
770 Ext
.iterate(request
.params
, function(name
, value
) {
771 if (Ext
.isArray(value
)) {
772 Ext
.each(value
, function(v
) {
773 formData
.append(name
, v
);
776 formData
.append(name
, value
);
779 delete request
.params
;
781 request
.data
= formData
;
784 return Ext
.Ajax
.request(request
);
790 * Performs an Ajax or Ext.Direct call to load values for this form.
792 * @param {Object} options
793 * The configuration when loading this form.
795 * The following are the configurations when loading via Ajax only:
797 * @param {String} options.url
798 * The url for the action (defaults to the form's {@link #url}).
800 * @param {String} options.method
801 * The form method to use (defaults to the form's {@link #method}, or GET if not defined).
803 * @param {Object} options.headers
804 * Request headers to set for the action.
806 * @param {Number} options.timeout
807 * The number is seconds the loading will timeout in.
809 * The following are the configurations when loading via Ajax or Direct:
811 * @param {Boolean} [options.autoAbort=false]
812 * `true` to abort any pending Ajax request prior to loading.
814 * @param {String/Object} options.params
815 * The params to pass when submitting this form (defaults to this forms {@link #baseParams}).
816 * Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.
818 * @param {String/Object} [options.waitMsg]
819 * If specified, the value which is passed to the loading {@link #masked mask}. See {@link #masked} for
822 * @param {Function} options.success
823 * The callback that will be invoked after a successful response. A response is successful if
824 * a response is received from the server and is a JSON object where the `success` property is set
825 * to `true`, `{"success": true}`.
827 * The function is passed the following parameters and can be used for loading via Ajax or Direct:
829 * @param {Ext.form.Panel} options.success.form
830 * The {@link Ext.form.Panel} that requested the load.
832 * @param {Object/Ext.direct.Event} options.success.result
833 * The result object returned by the server as a result of the load request. If the loading was done via Ext.Direct,
834 * will return the {@link Ext.direct.Event} instance, otherwise will return an Object.
836 * @param {Object} options.success.data
837 * The parsed data returned by the server.
839 * @param {Function} options.failure
840 * The callback that will be invoked after a failed transaction attempt.
842 * The function is passed the following parameters and can be used for loading via Ajax or Direct:
844 * @param {Ext.form.Panel} options.failure.form
845 * The {@link Ext.form.Panel} that requested the load.
847 * @param {Ext.form.Panel} options.failure.result
848 * The failed response or result object returned by the server which performed the operation.
850 * @param {Object} options.success.data
851 * The parsed data returned by the server.
853 * @param {Object} options.scope
854 * The scope in which to call the callback functions (The `this` reference for the callback functions).
856 * @return {Ext.data.Connection} The request object.
858 load : function(options
) {
859 options
= options
|| {};
863 url
= me
.getUrl() || options
.url
,
864 waitMsg
= options
.waitMsg
,
865 successFn = function(response
, data
) {
866 me
.setValues(data
.data
);
868 if (Ext
.isFunction(options
.success
)) {
869 options
.success
.call(options
.scope
|| me
, me
, response
, data
);
872 me
.fireEvent('load', me
, response
);
874 failureFn = function(response
, data
) {
875 if (Ext
.isFunction(options
.failure
)) {
876 options
.failure
.call(scope
, me
, response
, data
);
879 me
.fireEvent('exception', me
, response
);
883 if (options
.waitMsg
) {
884 if (typeof waitMsg
=== 'string') {
891 me
.setMasked(waitMsg
);
897 if (typeof load
=== 'string') {
898 load
= Ext
.direct
.Manager
.parseMethod(load
);
906 method
= load
.directCfg
.method
;
907 args
= method
.getArgs(me
.getParams(options
.params
), me
.getParamOrder(), me
.getParamsAsHash());
909 args
.push(function(data
, response
, success
) {
913 successFn(response
, data
);
915 failureFn(response
, data
);
919 return load
.apply(window
, args
);
922 return Ext
.Ajax
.request({
924 timeout
: (options
.timeout
|| this.getTimeout()) * 1000,
925 method
: options
.method
|| 'GET',
926 autoAbort
: options
.autoAbort
,
929 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
931 options
.headers
|| {}
933 callback: function(callbackOptions
, success
, response
) {
934 var responseText
= response
.responseText
,
935 statusResult
= Ext
.Ajax
.parseStatus(response
.status
, response
);
940 if (statusResult
&& responseText
.length
== 0) {
943 response
= Ext
.decode(responseText
);
944 success
= !!response
.success
;
947 successFn(response
, responseText
);
949 failureFn(response
, responseText
);
953 failureFn(response
, responseText
);
961 getParams : function(params
) {
962 return Ext
.apply({}, params
, this.getBaseParams());
966 * Sets the values of form fields in bulk. Example usage:
971 * username: 'edspencer'
974 * If there groups of checkbox fields with the same name, pass their values in an array. For example:
986 * @param {Object} values field name => value mapping object.
987 * @return {Ext.form.Panel} This form.
989 setValues: function(values
) {
990 var fields
= this.getFields(),
992 name
, field
, value
, ln
, i
, f
;
994 values
= values
|| {};
996 for (name
in values
) {
997 if (values
.hasOwnProperty(name
)) {
998 field
= fields
[name
];
999 value
= values
[name
];
1002 // If there are multiple fields with the same name. Checkboxes, radio fields and maybe event just normal fields..
1003 if (Ext
.isArray(field
)) {
1006 // Loop through each of the fields
1007 for (i
= 0; i
< ln
; i
++) {
1011 // If it is a radio field just use setGroupValue which will handle all of the radio fields
1012 f
.setGroupValue(value
);
1014 } else if (f
.isCheckbox
) {
1015 if (Ext
.isArray(value
)) {
1016 f
.setChecked((value
.indexOf(f
._value
) != -1));
1018 f
.setChecked((value
== f
._value
));
1021 // If it is a bunch of fields with the same name, check if the value is also an array, so we can map it
1023 if (Ext
.isArray(value
)) {
1024 f
.setValue(value
[i
]);
1029 if (field
.isRadio
|| field
.isCheckbox
) {
1030 // If the field is a radio or a checkbox
1031 field
.setChecked(value
);
1033 // If just a normal field
1034 field
.setValue(value
);
1038 if (me
.getTrackResetOnLoad()) {
1039 field
.resetOriginalValue();
1049 * Returns an object containing the value of each field in the form, keyed to the field's name.
1050 * For groups of checkbox fields with the same name, it will be arrays of values. For example:
1053 * name: "Jacky Nguyen", // From a TextField
1061 * @param {Boolean} [enabled] `true` to return only enabled fields.
1062 * @param {Boolean} [all] `true` to return all fields even if they don't have a
1063 * {@link Ext.field.Field#name name} configured.
1064 * @return {Object} Object mapping field name to its value.
1066 getValues: function(enabled
, all
) {
1067 var fields
= this.getFields(),
1069 isArray
= Ext
.isArray
,
1070 field
, value
, addValue
, bucket
, name
, ln
, i
;
1072 // Function which you give a field and a name, and it will add it into the values
1073 // object accordingly
1074 addValue = function(field
, name
) {
1075 if (!all
&& (!name
|| name
=== 'null') || field
.isFile
) {
1079 if (field
.isCheckbox
) {
1080 value
= field
.getSubmitValue();
1082 value
= field
.getValue();
1086 if (!(enabled
&& field
.getDisabled())) {
1087 // RadioField is a special case where the value returned is the fields valUE
1088 // ONLY if it is checked
1089 if (field
.isRadio
) {
1090 if (field
.isChecked()) {
1091 values
[name
] = value
;
1094 // Check if the value already exists
1095 bucket
= values
[name
];
1096 if (!Ext
.isEmpty(bucket
)) {
1097 // if it does and it isn't an array, we need to make it into an array
1098 // so we can push more
1099 if (!isArray(bucket
)) {
1100 bucket
= values
[name
] = [bucket
];
1103 // Check if it is an array
1104 if (isArray(value
)) {
1105 // Concat it into the other values
1106 bucket
= values
[name
] = bucket
.concat(value
);
1108 // If it isn't an array, just pushed more values
1112 values
[name
] = value
;
1118 // Loop through each of the fields, and add the values for those fields.
1119 for (name
in fields
) {
1120 if (fields
.hasOwnProperty(name
)) {
1121 field
= fields
[name
];
1123 if (isArray(field
)) {
1125 for (i
= 0; i
< ln
; i
++) {
1126 addValue(field
[i
], name
);
1129 addValue(field
, name
);
1138 * Resets all fields in the form back to their original values.
1139 * @return {Ext.form.Panel} This form.
1142 this.getFieldsAsArray().forEach(function(field
) {
1150 * A convenient method to disable all fields in this form.
1151 * @return {Ext.form.Panel} This form.
1153 doSetDisabled: function(newDisabled
) {
1154 this.getFieldsAsArray().forEach(function(field
) {
1155 field
.setDisabled(newDisabled
);
1164 getFieldsAsArray: function() {
1166 getFieldsFrom = function(item
) {
1171 if (item
.isContainer
) {
1172 item
.getItems().each(getFieldsFrom
);
1176 this.getItems().each(getFieldsFrom
);
1182 * Returns all {@link Ext.field.Field field} instances inside this form.
1183 * @param {Boolean} byName return only fields that match the given name, otherwise return all fields.
1184 * @return {Object/Array} All field instances, mapped by field name; or an array if `byName` is passed.
1186 getFields: function(byName
) {
1190 var getFieldsFrom = function(item
) {
1192 itemName
= item
.getName();
1194 if ((byName
&& itemName
== byName
) || typeof byName
== 'undefined') {
1195 if (fields
.hasOwnProperty(itemName
)) {
1196 if (!Ext
.isArray(fields
[itemName
])) {
1197 fields
[itemName
] = [fields
[itemName
]];
1200 fields
[itemName
].push(item
);
1202 fields
[itemName
] = item
;
1208 if (item
.isContainer
) {
1209 item
.items
.each(getFieldsFrom
);
1213 this.getItems().each(getFieldsFrom
);
1215 return (byName
) ? (fields
[byName
] || []) : fields
;
1219 * Returns an array of fields in this formpanel.
1220 * @return {Ext.field.Field[]} An array of fields in this form panel.
1223 getFieldsArray: function() {
1226 var getFieldsFrom = function(item
) {
1231 if (item
.isContainer
) {
1232 item
.items
.each(getFieldsFrom
);
1236 this.items
.each(getFieldsFrom
);
1241 getFieldsFromItem
: Ext
.emptyFn
,
1244 * Shows a generic/custom mask over a designated Element.
1245 * @param {String/Object} cfg Either a string message or a configuration object supporting
1246 * the following options:
1249 * message : 'Please Wait',
1253 * @param {Object} target
1254 * @return {Ext.form.Panel} This form
1255 * @deprecated 2.0.0 Please use {@link #setMasked} instead.
1257 showMask: function(cfg
, target
) {
1259 Ext
.Logger
.warn('showMask is now deprecated. Please use Ext.form.Panel#setMasked instead');
1262 cfg
= Ext
.isObject(cfg
) ? cfg
.message
: cfg
;
1270 this.setMasked(true);
1277 * Hides a previously shown wait mask (See {@link #showMask}).
1278 * @return {Ext.form.Panel} this
1279 * @deprecated 2.0.0 Please use {@link #unmask} or {@link #setMasked} instead.
1281 hideMask: function() {
1282 this.setMasked(false);
1287 * Returns the currently focused field
1288 * @return {Ext.field.Field} The currently focused field, if one is focused or `null`.
1291 getFocusedField: function() {
1292 var fields
= this.getFieldsArray(),
1296 for (i
= 0; i
< ln
; i
++) {
1298 if (field
.isFocused
) {
1307 * @return {Boolean/Ext.field.Field} The next field if one exists, or `false`.
1310 getNextField: function() {
1311 var fields
= this.getFieldsArray(),
1312 focusedField
= this.getFocusedField(),
1316 index
= fields
.indexOf(focusedField
);
1318 if (index
!== fields
.length
- 1) {
1320 return fields
[index
];
1328 * Tries to focus the next field in the form, if there is currently a focused field.
1329 * @return {Boolean/Ext.field.Field} The next field that was focused, or `false`.
1332 focusNextField: function() {
1333 var field
= this.getNextField();
1344 * @return {Boolean/Ext.field.Field} The next field if one exists, or `false`.
1346 getPreviousField: function() {
1347 var fields
= this.getFieldsArray(),
1348 focusedField
= this.getFocusedField(),
1352 index
= fields
.indexOf(focusedField
);
1356 return fields
[index
];
1364 * Tries to focus the previous field in the form, if there is currently a focused field.
1365 * @return {Boolean/Ext.field.Field} The previous field that was focused, or `false`.
1368 focusPreviousField: function() {
1369 var field
= this.getPreviousField();
1379 //<deprecated product=touch since=2.0>
1380 Ext
.deprecateClassMethod(this, {
1383 * @inheritdoc Ext.form.Panel#setRecord
1384 * @deprecated 2.0.0 Please use #setRecord instead.
1386 loadRecord
: 'setRecord',
1389 * @inheritdoc Ext.form.Panel#setRecord
1390 * @deprecated 2.0.0 Please use #setRecord instead.
1392 loadModel
: 'setRecord'
1396 constructor: function(config
) {
1398 * @cfg {Ext.XTemplate/String/String[]} waitTpl
1399 * The defined waitMsg template. Used for precise control over the masking agent used
1400 * to mask the FormPanel (or other Element) during form Ajax/submission actions. For more options, see
1401 * {@link #showMask} method.
1402 * @removed 2.0.0 Please use a custom {@link Ext.LoadMask} class and the {@link #masked} configuration
1403 * when {@link #method submitting} your form.
1407 * @cfg {Ext.dom.Element} waitMsgTarget The target of any mask shown on this form.
1408 * @removed 2.0.0 There is no need to set a mask target anymore. Please see the {@link #masked} configuration instead.
1410 if (config
&& config
.hasOwnProperty('waitMsgTarget')) {
1411 delete config
.waitMsgTarget
;
1414 this.callParent([config
]);