telegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchat
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
446 lines
14 KiB
446 lines
14 KiB
/** |
|
* FormPanel provides a standard container for forms. It is essentially a standard {@link Ext.panel.Panel} which |
|
* automatically creates a {@link Ext.form.Basic BasicForm} for managing any {@link Ext.form.field.Field} |
|
* objects that are added as descendants of the panel. It also includes conveniences for configuring and |
|
* working with the BasicForm and the collection of Fields. |
|
* |
|
* # Layout |
|
* |
|
* By default, FormPanel is configured with `{@link Ext.layout.container.Anchor layout:'anchor'}` for |
|
* the layout of its immediate child items. This can be changed to any of the supported container layouts. |
|
* The layout of sub-containers is configured in {@link Ext.container.Container#layout the standard way}. |
|
* |
|
* # BasicForm |
|
* |
|
* FormPanel class accepts all |
|
* of the config options supported by the {@link Ext.form.Basic} class, and will pass them along to |
|
* the internal BasicForm when it is created. |
|
* |
|
* The following events fired by the BasicForm will be re-fired by the FormPanel and can therefore be |
|
* listened for on the FormPanel itself: |
|
* |
|
* - {@link Ext.form.Basic#beforeaction beforeaction} |
|
* - {@link Ext.form.Basic#actionfailed actionfailed} |
|
* - {@link Ext.form.Basic#actioncomplete actioncomplete} |
|
* - {@link Ext.form.Basic#validitychange validitychange} |
|
* - {@link Ext.form.Basic#dirtychange dirtychange} |
|
* |
|
* # Field Defaults |
|
* |
|
* The {@link #fieldDefaults} config option conveniently allows centralized configuration of default values |
|
* for all fields added as descendants of the FormPanel. Any config option recognized by implementations |
|
* of {@link Ext.form.Labelable} may be included in this object. See the {@link #fieldDefaults} documentation |
|
* for details of how the defaults are applied. |
|
* |
|
* # Form Validation |
|
* |
|
* With the default configuration, form fields are validated on-the-fly while the user edits their values. |
|
* This can be controlled on a per-field basis (or via the {@link #fieldDefaults} config) with the field |
|
* config properties {@link Ext.form.field.Field#validateOnChange} and {@link Ext.form.field.Base#checkChangeEvents}, |
|
* and the FormPanel's config properties {@link #pollForChanges} and {@link #pollInterval}. |
|
* |
|
* Any component within the FormPanel can be configured with `formBind: true`. This will cause that |
|
* component to be automatically disabled when the form is invalid, and enabled when it is valid. This is most |
|
* commonly used for Button components to prevent submitting the form in an invalid state, but can be used on |
|
* any component type. |
|
* |
|
* For more information on form validation see the following: |
|
* |
|
* - {@link Ext.form.field.Field#validateOnChange} |
|
* - {@link #pollForChanges} and {@link #pollInterval} |
|
* - {@link Ext.form.field.VTypes} |
|
* - {@link Ext.form.Basic#doAction BasicForm.doAction clientValidation notes} |
|
* |
|
* # Form Submission |
|
* |
|
* By default, Ext Forms are submitted through Ajax, using {@link Ext.form.action.Action}. See the documentation for |
|
* {@link Ext.form.Basic} for details. |
|
* |
|
* # Example usage |
|
* |
|
* @example |
|
* Ext.create('Ext.form.Panel', { |
|
* title: 'Simple Form', |
|
* bodyPadding: 5, |
|
* width: 350, |
|
* |
|
* // The form will submit an AJAX request to this URL when submitted |
|
* url: 'save-form.php', |
|
* |
|
* // Fields will be arranged vertically, stretched to full width |
|
* layout: 'anchor', |
|
* defaults: { |
|
* anchor: '100%' |
|
* }, |
|
* |
|
* // The fields |
|
* defaultType: 'textfield', |
|
* items: [{ |
|
* fieldLabel: 'First Name', |
|
* name: 'first', |
|
* allowBlank: false |
|
* },{ |
|
* fieldLabel: 'Last Name', |
|
* name: 'last', |
|
* allowBlank: false |
|
* }], |
|
* |
|
* // Reset and Submit buttons |
|
* buttons: [{ |
|
* text: 'Reset', |
|
* handler: function() { |
|
* this.up('form').getForm().reset(); |
|
* } |
|
* }, { |
|
* text: 'Submit', |
|
* formBind: true, //only enabled once the form is valid |
|
* disabled: true, |
|
* handler: function() { |
|
* var form = this.up('form').getForm(); |
|
* if (form.isValid()) { |
|
* form.submit({ |
|
* success: function(form, action) { |
|
* Ext.Msg.alert('Success', action.result.msg); |
|
* }, |
|
* failure: function(form, action) { |
|
* Ext.Msg.alert('Failed', action.result.msg); |
|
* } |
|
* }); |
|
* } |
|
* } |
|
* }], |
|
* renderTo: Ext.getBody() |
|
* }); |
|
* |
|
*/ |
|
Ext.define('Ext.form.Panel', { |
|
extend:'Ext.panel.Panel', |
|
mixins: { |
|
fieldAncestor: 'Ext.form.FieldAncestor' |
|
}, |
|
alias: 'widget.form', |
|
alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'], |
|
requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'], |
|
|
|
/** |
|
* @cfg {Boolean} pollForChanges |
|
* If set to `true`, sets up an interval task (using the {@link #pollInterval}) in which the |
|
* panel's fields are repeatedly checked for changes in their values. This is in addition to the normal detection |
|
* each field does on its own input element, and is not needed in most cases. It does, however, provide a |
|
* means to absolutely guarantee detection of all changes including some edge cases in some browsers which |
|
* do not fire native events. Defaults to `false`. |
|
*/ |
|
|
|
/** |
|
* @cfg {Number} pollInterval |
|
* Interval in milliseconds at which the form's fields are checked for value changes. Only used if |
|
* the {@link #pollForChanges} option is set to `true`. Defaults to 500 milliseconds. |
|
*/ |
|
|
|
/** |
|
* @cfg {Ext.enums.Layout/Object} layout |
|
* The {@link Ext.container.Container#layout} for the form panel's immediate child items. |
|
*/ |
|
layout: 'anchor', |
|
|
|
ariaRole: 'form', |
|
|
|
basicFormConfigs: [ |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#api |
|
*/ |
|
'api', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#baseParams |
|
*/ |
|
'baseParams', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#errorReader |
|
*/ |
|
'errorReader', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#jsonSubmit |
|
*/ |
|
'jsonSubmit', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#method |
|
*/ |
|
'method', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#paramOrder |
|
*/ |
|
'paramOrder', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#paramsAsHash |
|
*/ |
|
'paramsAsHash', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#reader |
|
*/ |
|
'reader', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#standardSubmit |
|
*/ |
|
'standardSubmit', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#timeout |
|
*/ |
|
'timeout', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#trackResetOnLoad |
|
*/ |
|
'trackResetOnLoad', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#url |
|
*/ |
|
'url', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#waitMsgTarget |
|
*/ |
|
'waitMsgTarget', |
|
/** |
|
* @cfg |
|
* @inheritdoc Ext.form.Basic#waitTitle |
|
*/ |
|
'waitTitle' |
|
], |
|
|
|
initComponent: function() { |
|
var me = this; |
|
|
|
if (me.frame) { |
|
me.border = false; |
|
} |
|
|
|
me.initFieldAncestor(); |
|
me.callParent(); |
|
|
|
me.relayEvents(me.form, [ |
|
/** |
|
* @event beforeaction |
|
* @inheritdoc Ext.form.Basic#beforeaction |
|
*/ |
|
'beforeaction', |
|
/** |
|
* @event actionfailed |
|
* @inheritdoc Ext.form.Basic#actionfailed |
|
*/ |
|
'actionfailed', |
|
/** |
|
* @event actioncomplete |
|
* @inheritdoc Ext.form.Basic#actioncomplete |
|
*/ |
|
'actioncomplete', |
|
/** |
|
* @event validitychange |
|
* @inheritdoc Ext.form.Basic#validitychange |
|
*/ |
|
'validitychange', |
|
/** |
|
* @event dirtychange |
|
* @inheritdoc Ext.form.Basic#dirtychange |
|
*/ |
|
'dirtychange' |
|
]); |
|
|
|
// Start polling if configured |
|
if (me.pollForChanges) { |
|
me.startPolling(me.pollInterval || 500); |
|
} |
|
}, |
|
|
|
initItems: function() { |
|
// Create the BasicForm |
|
this.callParent(); |
|
this.initMonitor(); |
|
this.form = this.createForm(); |
|
}, |
|
|
|
// Initialize the BasicForm after all layouts have been completed. |
|
afterFirstLayout: function() { |
|
this.callParent(arguments); |
|
this.form.initialize(); |
|
}, |
|
|
|
/** |
|
* @private |
|
*/ |
|
createForm: function() { |
|
var cfg = {}, |
|
props = this.basicFormConfigs, |
|
len = props.length, |
|
i = 0, |
|
prop; |
|
|
|
for (; i < len; ++i) { |
|
prop = props[i]; |
|
cfg[prop] = this[prop]; |
|
} |
|
return new Ext.form.Basic(this, cfg); |
|
}, |
|
|
|
/** |
|
* Provides access to the {@link Ext.form.Basic Form} which this Panel contains. |
|
* @return {Ext.form.Basic} The {@link Ext.form.Basic Form} which this Panel contains. |
|
*/ |
|
getForm: function() { |
|
return this.form; |
|
}, |
|
|
|
/** |
|
* Loads an {@link Ext.data.Model} into this form (internally just calls {@link Ext.form.Basic#loadRecord}) |
|
* See also {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad}. The fields in the model are mapped to |
|
* fields in the form by matching either the {@link Ext.form.field.Base#name} or {@link Ext.Component#itemId}. |
|
* @param {Ext.data.Model} record The record to load |
|
* @return {Ext.form.Basic} The Ext.form.Basic attached to this FormPanel |
|
*/ |
|
loadRecord: function(record) { |
|
return this.getForm().loadRecord(record); |
|
}, |
|
|
|
/** |
|
* Returns the currently loaded Ext.data.Model instance if one was loaded via {@link #loadRecord}. |
|
* @return {Ext.data.Model} The loaded instance |
|
*/ |
|
getRecord: function() { |
|
return this.getForm().getRecord(); |
|
}, |
|
|
|
/** |
|
* Persists the values in this form into the passed {@link Ext.data.Model} object in a beginEdit/endEdit block. |
|
* If the record is not specified, it will attempt to update (if it exists) the record provided to {@link #loadRecord}. |
|
* @param {Ext.data.Model} [record] The record to edit |
|
* @return {Ext.form.Basic} The Ext.form.Basic attached to this FormPanel |
|
*/ |
|
updateRecord: function(record) { |
|
return this.getForm().updateRecord(record); |
|
}, |
|
|
|
/** |
|
* Convenience function for fetching the current value of each field in the form. This is the same as calling |
|
* {@link Ext.form.Basic#getValues this.getForm().getValues()}. |
|
* |
|
* @inheritdoc Ext.form.Basic#getValues |
|
*/ |
|
getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) { |
|
return this.getForm().getValues(asString, dirtyOnly, includeEmptyText, useDataValues); |
|
}, |
|
|
|
/** |
|
* Convenience function to check if the form has any dirty fields. This is the same as calling |
|
* {@link Ext.form.Basic#isDirty this.getForm().isDirty()}. |
|
* |
|
* @inheritdoc Ext.form.Basic#isDirty |
|
*/ |
|
isDirty: function () { |
|
return this.form.isDirty(); |
|
}, |
|
|
|
/** |
|
* Convenience function to check if the form has all valid fields. This is the same as calling |
|
* {@link Ext.form.Basic#isValid this.getForm().isValid()}. |
|
* |
|
* @inheritdoc Ext.form.Basic#isValid |
|
*/ |
|
isValid: function () { |
|
return this.form.isValid(); |
|
}, |
|
|
|
/** |
|
* Convenience function reset the form. This is the same as calling |
|
* {@link Ext.form.Basic#reset this.getForm().reset()}. |
|
* |
|
* @inheritdoc Ext.form.Basic#reset |
|
*/ |
|
reset: function() { |
|
this.form.reset(); |
|
}, |
|
|
|
/** |
|
* Convenience function to check if the form has any invalid fields. This is the same as calling |
|
* {@link Ext.form.Basic#hasInvalidField this.getForm().hasInvalidField()}. |
|
* |
|
* @inheritdoc Ext.form.Basic#hasInvalidField |
|
*/ |
|
hasInvalidField: function () { |
|
return this.form.hasInvalidField(); |
|
}, |
|
|
|
beforeDestroy: function() { |
|
this.stopPolling(); |
|
this.form.destroy(); |
|
this.callParent(); |
|
}, |
|
|
|
/** |
|
* This is a proxy for the underlying BasicForm's {@link Ext.form.Basic#load} call. |
|
* @param {Object} options The options to pass to the action (see {@link Ext.form.Basic#load} and |
|
* {@link Ext.form.Basic#doAction} for details) |
|
*/ |
|
load: function(options) { |
|
this.form.load(options); |
|
}, |
|
|
|
/** |
|
* This is a proxy for the underlying BasicForm's {@link Ext.form.Basic#submit} call. |
|
* @param {Object} options The options to pass to the action (see {@link Ext.form.Basic#submit} and |
|
* {@link Ext.form.Basic#doAction} for details) |
|
*/ |
|
submit: function(options) { |
|
this.form.submit(options); |
|
}, |
|
|
|
/** |
|
* Start an interval task to continuously poll all the fields in the form for changes in their |
|
* values. This is normally started automatically by setting the {@link #pollForChanges} config. |
|
* @param {Number} interval The interval in milliseconds at which the check should run. |
|
*/ |
|
startPolling: function(interval) { |
|
this.stopPolling(); |
|
var task = new Ext.util.TaskRunner(interval); |
|
task.start({ |
|
interval: 0, |
|
run: this.checkChange, |
|
scope: this |
|
}); |
|
this.pollTask = task; |
|
}, |
|
|
|
/** |
|
* Stop a running interval task that was started by {@link #startPolling}. |
|
*/ |
|
stopPolling: function() { |
|
var task = this.pollTask; |
|
if (task) { |
|
task.stopAll(); |
|
delete this.pollTask; |
|
} |
|
}, |
|
|
|
/** |
|
* Forces each field within the form panel to |
|
* {@link Ext.form.field.Field#checkChange check if its value has changed}. |
|
*/ |
|
checkChange: function() { |
|
var fields = this.form.getFields().items, |
|
f, |
|
fLen = fields.length; |
|
|
|
for (f = 0; f < fLen; f++) { |
|
fields[f].checkChange(); |
|
} |
|
} |
|
});
|
|
|