/** * @class Ext.form.Field *This mixin provides a common interface for the logical behavior of form fields, including:
*
When implementing custom fields, it is likely that you will want to extend the {@link Ext.form.BaseField} * component class rather than using this mixin directly, as it contains additional logic for generating an * actual DOM complete with {@link Ext.form.Labelable label and error message} display.
*If you want to implement this mixin directly and don't want to extend {@link Ext.form.BaseField}, then * you will most likely want to override the following methods with custom implementations: {@link #getRawValue}, * {@link #setRawValue}, and {@link #getErrors}. If your field implementation handles custom data types you may * also want to override {@link #valueToRaw} and {@link #rawToValue}. Other methods may be overridden as needed * but their base implementations should be sufficient for common cases.
*/ Ext.define('Ext.form.Field', { /** * @property isFormField * @type {Boolean} * Flag denoting that this component is a Field. Always true. */ isFormField : true, /** * @cfg {Mixed} value A value to initialize this field with (defaults to undefined). */ /** * @cfg {String} name The name of the field (defaults to undefined). This is used as the parameter * name when including the field value in a {@link Ext.form.Basic#submit form submit()}. If no name is * configured, it falls back to the {@link #inputId}. To prevent the field from being included in the * form submit, set {@link #submitValue} to false. */ /** * @cfg {Boolean} disabled True to disable the field (defaults to false). Disabled Fields will not be * {@link Ext.form.Basic#submit submitted}. */ disabled : false, /** * @cfg {Boolean} submitValue Setting this to false will prevent the field from being * {@link Ext.form.Basic#submit submitted} even when it is not disabled. Defaults to true. */ submitValue: true, /** * @cfg {Boolean} validateOnChange *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.BaseField#checkChangeEvents}for controlling how changes to the field's value are detected.
*/ validateOnChange: true, /** * 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} 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} 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} 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; /** * 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
.
* @type Mixed
* @property originalValue
*/
me.originalValue = me._lastValue = me.value;
// Set the initial value and perform conversion/validation
me.setValue(me.value);
me.clearInvalid();
},
/**
* Returns the {@link Ext.form.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#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.Date}), as the result of calling {@link #rawToValue} on
* the field's {@link #processRawValue processed} String value. To return the raw String value, see {@link #getRawValue}.
* @return {Mixed} value The field value
*/
getValue: function() {
var me = this,
val = me.rawToValue(me.processRawValue(me.getRawValue()));
me.value = val;
return val;
},
/**
* Sets a data value into the field and runs the change detection and validation. To set the value directly
* without these inspections see {@link #setRawValue}.
* @param {Mixed} value The value to set
* @return {Ext.form.Field} this
*/
setValue: function(value) {
var me = this;
me.value = value;
me.setRawValue(this.valueToRaw(value));
me.checkChange();
return me;
},
/**
* Returns the raw value of the field, without performing any normalization, conversion, or validation.
* To get a normalized and converted value see {@link #getValue}.
* @return {String} value The raw String value of the field
*/
getRawValue: function() {
var me = this,
value = Ext.value(me.rawValue, '');
me.rawValue = value;
return value;
},
/**
* Sets the field's raw value directly, bypassing {@link #valueToRaw value conversion}, change detection, and
* validation. To set the value with these additional inspections see {@link #setValue}.
* @param {Mixed} value The value to set
* @return {Mixed} value The field value that is set
*/
setRawValue: function(value) {
value = Ext.value(value, '');
this.rawValue = value;
return value;
},
/**
* Converts a mixed-type value to a raw representation suitable for displaying in the field. This allows * controlling how value objects passed to {@link #setValue} are shown to the user, including localization. * For instance, for a {@link Ext.form.Date}, this would control how a Date object passed to {@link #setValue} * would be converted to a String for display in the field.
*See {@link #rawToValue} for the opposite conversion.
*The base implementation simply does a standard toString conversion, and converts * {@link Ext#isEmpty empty values} to an empty string.
* @param {Mixed} value The mixed-type value to convert to the raw representation. * @return {Mixed} The converted raw value. */ valueToRaw: function(value) { return '' + Ext.value(value, ''); }, /** *Converts a raw input field value into a mixed-type value that is suitable for this particular field type. * This allows controlling the normalization and conversion of user-entered values into field-type-appropriate * values, e.g. a Date object for {@link Ext.form.Date}, and is invoked by {@link #getValue}.
*It is up to individual implementations to decide how to handle raw values that cannot be successfully * converted to the desired object type.
*See {@link #valueToRaw} for the opposite conversion.
*The base implementation does no conversion, returning the raw value untouched.
* @param {Mixed} rawValue * @return {Mixed} The converted value. */ rawToValue: function(rawValue) { return rawValue; }, /** * Performs any necessary manipulation of a raw field value to prepare it for {@link #rawToValue conversion} * and/or {@link #validate validation}, for instance stripping out ignored characters. In the base implementation * it does nothing; individual subclasses may override this as needed. * @param {Mixed} value The unprocessed string value * @return {Mixed} The processed string value */ processRawValue: function(value) { return value; }, /** *Returns the value that would be included in a standard form submit for this field. This will be combined * with the field's name to form a name=value pair in the submitted parameters. If an empty string is returned * then just the name= will be submitted; if null is returned then nothing will be submitted.
*Note that the value returned will have been {@link #processRawValue processed} but may or may not have * been successfully {@link #validate validated}.
* @return {String} The value to be submitted, or null. */ getSubmitValue: function() { var me = this; return (me.disabled || !me.submitValue) ? null : me.processRawValue(me.getRawValue()); }, /** * 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(){ this.setValue(this.originalValue); this.clearInvalid(); }, /** *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 {@lnk #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() { return !this.disabled && String(this.getValue()) !== String(this.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. */ checkDirtyChange: function() { var me = this, isDirty = me.isDirty; if (isDirty !== me.wasDirty) { me.fireEvent('dirtychange', me, isDirty); me.wasDirty = isDirty; } }, /** * Validates the field and if its validity has changed since the last time it was checked, * fires the {@link #validitychange} event. * @return {Boolean} true if the validitychange event was fired, false if not. */ checkValidityChange: function() { var me = this, changed = false, isValid = me.validate(); if (isValid !== me.wasValid) { me.fireEvent('validitychange', me, isValid); me.wasValid = isValid; changed = true; } return changed; }, /** *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. Note: {@link #disabled} fields are always treated as valid.
*Logically this is identical to the {@link #validate} method, but 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 || me.getErrors().length === 0; }, /** *Returns whether or not the field value is currently valid by {@link #getErrors validating} the * field's current value. Note: {@link #disabled} fields are always treated as valid.
*Logically this is identical to the {@link #isValid} method, but unlike that method this one * may have side-effects such as triggering error message display.
* @return {Boolean} True if the value is valid, else false */ validate : function() { return this.isValid(); } });