X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/form/field/Field.js?ds=inline
diff --git a/src/form/field/Field.js b/src/form/field/Field.js
new file mode 100644
index 00000000..6603d9f4
--- /dev/null
+++ b/src/form/field/Field.js
@@ -0,0 +1,404 @@
+/**
+ * @class Ext.form.field.Field
+
+This mixin provides a common interface for the logical behavior and state of form fields, including:
+
+- Getter and setter methods for field values
+- Events and methods for tracking value and validity changes
+- Methods for triggering validation
+
+**NOTE**: When implementing custom fields, it is most likely that you will want to extend the {@link Ext.form.field.Base}
+component class rather than using this mixin directly, as BaseField contains additional logic for generating an
+actual DOM complete with {@link Ext.form.Labelable label and error message} display and a form input field,
+plus methods that bind the Field value getters and setters to the input field's value.
+
+If you do want to implement this mixin directly and don't want to extend {@link Ext.form.field.Base}, then
+you will most likely want to override the following methods with custom implementations: {@link #getValue},
+{@link #setValue}, and {@link #getErrors}. Other methods may be overridden as needed but their base
+implementations should be sufficient for common cases. You will also need to make sure that {@link #initField}
+is called during the component's initialization.
+
+ * @markdown
+ * @docauthor Jason Johnston
Specifies whether this field should be validated immediately whenever a change in its value is detected. + * Defaults to true. If the validation results in a change in the field's validity, a + * {@link #validitychange} event will be fired. This allows the field to show feedback about the + * validity of its contents immediately as the user is typing.
+ *When set to false, feedback will not be immediate. However the form will still be validated + * before submitting if the clientValidation option to {@link Ext.form.Basic#doAction} is + * enabled, or if the field or form are validated manually.
+ *See also {@link Ext.form.field.Base#checkChangeEvents}for controlling how changes to the field's value are detected.
+ */ + validateOnChange: true, + + /** + * @private + */ + suspendCheckChange: 0, + + /** + * Initializes this Field mixin on the current instance. Components using this mixin should call + * this method during their own initialization process. + */ + initField: function() { + this.addEvents( + /** + * @event change + * Fires when a user-initiated change is detected in the value of the field. + * @param {Ext.form.field.Field} this + * @param {Mixed} newValue The new value + * @param {Mixed} oldValue The original value + */ + 'change', + /** + * @event validitychange + * Fires when a change in the field's validity is detected. + * @param {Ext.form.field.Field} this + * @param {Boolean} isValid Whether or not the field is now valid + */ + 'validitychange', + /** + * @event dirtychange + * Fires when a change in the field's {@link #isDirty} state is detected. + * @param {Ext.form.field.Field} this + * @param {Boolean} isDirty Whether or not the field is now dirty + */ + 'dirtychange' + ); + + this.initValue(); + }, + + /** + * @protected + * Initializes the field's value based on the initial config. + */ + initValue: function() { + var me = this; + + /** + * @property originalValue + * @type Mixed + * The original value of the field as configured in the {@link #value} configuration, or as loaded by + * the last form load operation if the form's {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad} + * setting istrue
.
+ */
+ me.originalValue = me.lastValue = me.value;
+
+ // Set the initial value - prevent validation on initial set
+ me.suspendCheckChange++;
+ me.setValue(me.value);
+ me.suspendCheckChange--;
+ },
+
+ /**
+ * Returns the {@link Ext.form.field.Field#name name} attribute of the field. This is used as the parameter
+ * name when including the field value in a {@link Ext.form.Basic#submit form submit()}.
+ * @return {String} name The field {@link Ext.form.field.Field#name name}
+ */
+ getName: function() {
+ return this.name;
+ },
+
+ /**
+ * Returns the current data value of the field. The type of value returned is particular to the type of the
+ * particular field (e.g. a Date object for {@link Ext.form.field.Date}).
+ * @return {Mixed} value The field value
+ */
+ getValue: function() {
+ return this.value;
+ },
+
+ /**
+ * Sets a data value into the field and runs the change detection and validation.
+ * @param {Mixed} value The value to set
+ * @return {Ext.form.field.Field} this
+ */
+ setValue: function(value) {
+ var me = this;
+ me.value = value;
+ me.checkChange();
+ return me;
+ },
+
+ /**
+ * Returns whether two field {@link #getValue values} are logically equal. Field implementations may override
+ * this to provide custom comparison logic appropriate for the particular field's data type.
+ * @param {Mixed} value1 The first value to compare
+ * @param {Mixed} value2 The second value to compare
+ * @return {Boolean} True if the values are equal, false if inequal.
+ */
+ isEqual: function(value1, value2) {
+ return String(value1) === String(value2);
+ },
+
+ /**
+ * Returns the parameter(s) that would be included in a standard form submit for this field. Typically this + * will be an object with a single name-value pair, the name being this field's {@link #getName name} and the + * value being its current stringified value. More advanced field implementations may return more than one + * name-value pair.
+ *Note that the values returned from this method are not guaranteed to have been successfully + * {@link #validate validated}.
+ * @return {Object} A mapping of submit parameter names to values; each value should be a string, or an array + * of strings if that particular name has multiple values. It can also return null if there are no + * parameters to be submitted. + */ + getSubmitData: function() { + var me = this, + data = null; + if (!me.disabled && me.submitValue && !me.isFileUpload()) { + data = {}; + data[me.getName()] = '' + me.getValue(); + } + return data; + }, + + /** + *Returns the value(s) that should be saved to the {@link Ext.data.Model} instance for this field, when + * {@link Ext.form.Basic#updateRecord} is called. Typically this will be an object with a single name-value + * pair, the name being this field's {@link #getName name} and the value being its current data value. More + * advanced field implementations may return more than one name-value pair. The returned values will be + * saved to the corresponding field names in the Model.
+ *Note that the values returned from this method are not guaranteed to have been successfully + * {@link #validate validated}.
+ * @return {Object} A mapping of submit parameter names to values; each value should be a string, or an array + * of strings if that particular name has multiple values. It can also return null if there are no + * parameters to be submitted. + */ + getModelData: function() { + var me = this, + data = null; + if (!me.disabled && !me.isFileUpload()) { + data = {}; + data[me.getName()] = me.getValue(); + } + return data; + }, + + /** + * Resets the current field value to the originally loaded value and clears any validation messages. + * See {@link Ext.form.Basic}.{@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad} + */ + reset : function(){ + var me = this; + + me.setValue(me.originalValue); + me.clearInvalid(); + // delete here so we reset back to the original state + delete me.wasValid; + }, + + /** + * Resets the field's {@link #originalValue} property so it matches the current {@link #getValue value}. + * This is called by {@link Ext.form.Basic}.{@link Ext.form.Basic#setValues setValues} if the form's + * {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad} property is set to true. + */ + resetOriginalValue: function() { + this.originalValue = this.getValue(); + this.checkDirty(); + }, + + /** + *Checks whether the value of the field has changed since the last time it was checked. If the value + * has changed, it:
+ *Returns true if the value of this Field has been changed from its {@link #originalValue}. + * Will always return false if the field is disabled.
+ *Note that if the owning {@link Ext.form.Basic form} was configured with + * {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad} + * then the {@link #originalValue} is updated when the values are loaded by + * {@link Ext.form.Basic}.{@link Ext.form.Basic#setValues setValues}.
+ * @return {Boolean} True if this field has been changed from its original value (and + * is not disabled), false otherwise. + */ + isDirty : function() { + var me = this; + return !me.disabled && !me.isEqual(me.getValue(), me.originalValue); + }, + + /** + * Checks the {@link #isDirty} state of the field and if it has changed since the last time + * it was checked, fires the {@link #dirtychange} event. + */ + checkDirty: function() { + var me = this, + isDirty = me.isDirty(); + if (isDirty !== me.wasDirty) { + me.fireEvent('dirtychange', me, isDirty); + me.onDirtyChange(isDirty); + me.wasDirty = isDirty; + } + }, + + /** + * @private Called when the field's dirty state changes. + * @param {Boolean} isDirty + */ + onDirtyChange: Ext.emptyFn, + + /** + *Runs this field's validators and returns an array of error messages for any validation failures. + * This is called internally during validation and would not usually need to be used manually.
+ *Each subclass should override or augment the return value to provide their own errors.
+ * @param {Mixed} value The value to get errors for (defaults to the current field value) + * @return {Array} All error messages for this field; an empty Array if none. + */ + getErrors: function(value) { + return []; + }, + + /** + *Returns whether or not the field value is currently valid by {@link #getErrors validating} the + * field's current value. The {@link #validitychange} event will not be fired; use {@link #validate} + * instead if you want the event to fire. Note: {@link #disabled} fields are always treated as valid.
+ *Implementations are encouraged to ensure that this method does not have side-effects such as + * triggering error message display.
+ * @return {Boolean} True if the value is valid, else false + */ + isValid : function() { + var me = this; + return me.disabled || Ext.isEmpty(me.getErrors()); + }, + + /** + *Returns whether or not the field value is currently valid by {@link #getErrors validating} the + * field's current value, and fires the {@link #validitychange} event if the field's validity has + * changed since the last validation. Note: {@link #disabled} fields are always treated as valid.
+ *Custom implementations of this method are allowed to have side-effects such as triggering error + * message display. To validate without side-effects, use {@link #isValid}.
+ * @return {Boolean} True if the value is valid, else false + */ + validate : function() { + var me = this, + isValid = me.isValid(); + if (isValid !== me.wasValid) { + me.wasValid = isValid; + me.fireEvent('validitychange', me, isValid); + } + return isValid; + }, + + /** + * A utility for grouping a set of modifications which may trigger value changes into a single + * transaction, to prevent excessive firing of {@link #change} events. This is useful for instance + * if the field has sub-fields which are being updated as a group; you don't want the container + * field to check its own changed state for each subfield change. + * @param fn A function containing the transaction code + */ + batchChanges: function(fn) { + this.suspendCheckChange++; + fn(); + this.suspendCheckChange--; + this.checkChange(); + }, + + /** + * Returns whether this Field is a file upload field; if it returns true, forms will use + * special techniques for {@link Ext.form.Basic#submit submitting the form} via AJAX. See + * {@link Ext.form.Basic#hasUpload} for details. If this returns true, the {@link #extractFileInput} + * method must also be implemented to return the corresponding file input element. + * @return {Boolean} + */ + isFileUpload: function() { + return false; + }, + + /** + * Only relevant if the instance's {@link #isFileUpload} method returns true. Returns a reference + * to the file input DOM element holding the user's selected file. The input will be appended into + * the submission form and will not be returned, so this method should also create a replacement. + * @return {HTMLInputElement} + */ + extractFileInput: function() { + return null; + }, + + /** + *Associate one or more error messages with this field. Components using this mixin should implement + * this method to update the component's rendering to display the messages.
+ *Note: this method does not cause the Field's {@link #validate} or {@link #isValid} methods to
+ * return false
if the value does pass validation. So simply marking a Field as invalid
+ * will not prevent submission of forms submitted with the {@link Ext.form.action.Submit#clientValidation}
+ * option set.
Clear any invalid styles/messages for this field. Components using this mixin should implement + * this method to update the components rendering to clear any existing messages.
+ *Note: this method does not cause the Field's {@link #validate} or {@link #isValid} methods to
+ * return true
if the value does not pass validation. So simply clearing a field's errors
+ * will not necessarily allow submission of forms submitted with the {@link Ext.form.action.Submit#clientValidation}
+ * option set.