Recently, one of my clients needed to have a date/time field to update/create their records. So I googled a bit and found a great sample/extension for my existing project.
Yes, it is
Ext.ux.form.field.DateTime . However the existing extension does not have validation function so I just made a few changes on it.
/**
* @auther Elvis Hsu
* @class Ext.ux.form.field.DateTime
* @extends Ext.form.FieldContainer
*
* inspired by http://www.sencha.com/forum/showthread.php?134345-Ext.ux.form.field.DateTime
* This class is used for user input
*/
Ext . define ( ' Ext.ux.form.field.DateTime ' , {
extend : ' Ext.form.FieldContainer ' ,
mixins : {
field : ' Ext.form.field.Field '
},
alias : ' widget.datetimefield ' ,
layout : ' hbox ' ,
height : 22 ,
/**
* set combine errors to true for showing errors
*/
combineErrors : true ,
/**
* set msg target to side
*/
msgTarget : ' side ' ,
/**
* we want hbox layout
*/
layout : ' hbox ' ,
/**
* set readonly to false
*/
readOnly : false ,
/**
* @cfg {String} dateFormat
* Convenience config for specifying the format of the date portion.
* This value is overridden if format is specified in the dateConfig.
* The default is 'Y-m-d'
*/
dateFormat : ' Y-m-d ' ,
/**
* @cfg {String} timeFormat
* Convenience config for specifying the format of the time portion.
* This value is overridden if format is specified in the timeConfig.
* The default is 'H:i:s'
*/
timeFormat : ' H:i:s ' ,
/**
* the datefield configurations
*/
dateConfig :{},
/**
* the time field configurations
*/
timeConfig :{},
/**
* The actual date value
*/
dateValue : null ,
/**
* @property dateField
* @type Ext.form.field.Date
*/
dateField : null ,
/**
* @property timeField
* @type Ext.form.field.Time
*/
timeField : null ,
/**
* initialising the components
*/
initComponent : function () {
var me = this ,
key ,
tab ;
// set default to no items
me . items = me . items || [];
me . dateField = Ext . create ( ' Ext.form.field.Date ' , Ext . apply ({
format : me . dateFormat ,
flex : 1 ,
isFormField : false , //exclude from field query's
submitValue : false
}, me . dateConfig ));
me . items . push ( me . dateField );
me . timeField = Ext . create ( ' Ext.form.field.Time ' , Ext . apply ({
format : me . timeFormat ,
flex : 1 ,
isFormField : false , //exclude from field query's
submitValue : false
}, me . timeConfig ));
me . items . push ( me . timeField );
for ( var i = 0 ; i < me . items . length ; i ++ ) {
me . items [ i ]. on ( ' focus ' , Ext . bind ( me . onItemFocus , me ));
me . items [ i ]. on ( ' blur ' , Ext . bind ( me . onItemBlur , me ));
me . items [ i ]. on ( ' specialkey ' , function ( field , event ){
key = event . getKey ();
tab = ( key == event . TAB );
if ( tab & amp ; & amp ; me . focussedItem == me . dateField ) {
event . stopEvent ();
me . timeField . focus ();
return ;
}
me . fireEvent ( ' specialkey ' , field , event );
});
}
me . callParent ();
// this dummy is necessary because Ext.Editor will not check whether an inputEl is present or not
me . inputEl = {
dom :{},
swallowEvent : function (){}
};
me . initField ();
},
/**
* Try to focus this component.
* @param {Boolean} [selectText] If applicable, true to also select the text in this component
* @param {Boolean/Number} [delay] Delay the focus this number of milliseconds (true for 10 milliseconds).
* @return {Ext.Component} this
*/
focus : function (){
this . callParent ();
this . dateField . focus ();
},
onItemFocus : function ( item ){
if ( this . blurTask ){
this . blurTask . cancel ();
}
this . focussedItem = item ;
},
onItemBlur : function ( item ){
var me = this ;
if ( item != me . focussedItem ){ return ; }
// 100ms to focus a new item that belongs to us, otherwise we will assume the user left the field
me . blurTask = new Ext . util . DelayedTask ( function (){
me . fireEvent ( ' blur ' , me );
});
me . blurTask . delay ( 100 );
},
/**
* 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 {Object} value The field value
*/
getValue : function () {
var me = this ,
value = null ,
date = me . dateField . getSubmitValue (),
time = me . timeField . getSubmitValue ();
if ( date ){
if ( time ){
var format = me . getFormat ()
value = Ext . Date . parse ( date + ' ' + time , format )
} else {
value = me . dateField . getValue ()
}
}
return value
},
/**
* Sets a data value into the field and runs the change detection and validation.
* @param {Object} value The value to set
* @return {Ext.form.field.Field} this
*/
setValue : function ( value ){
if ( Ext . isString ( value )){
value = Ext . Date . parse ( value , this . getFormat ()); //this.dateTimeFormat
}
this . dateField . setValue ( value );
this . timeField . setValue ( value );
},
/**
* 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 () {
var me = this ;
me . originalValue = me . getValue ();
me . dateField . resetOriginalValue ();
me . timeField . resetOriginalValue ();
me . checkDirty ();
},
/**
* 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 {@link #getSubmitData 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 ,
format = me . getFormat (),
value = me . getValue ();
return value ? Ext . Date . format ( value , format ) : null ;
},
/**
* 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 & amp ; & amp ; me . submitValue & amp ; & amp ; ! me . isFileUpload ()) {
data = {};
data [ me . getName ()] = '' + me . getSubmitValue ();
}
return data ;
},
/**
* Gets the current date time field format
*/
getFormat : function (){
var me = this ;
return ( me . dateField . submitFormat || me . dateField . format ) + " " + ( me . timeField . submitFormat || me . timeField . format )
},
/**
* Replaces any existing {@link #minValue} with the new value and refreshes the Date picker.
* @param {Date} value The minimum date that can be selected
*/
setMinValue : function ( date ){
var me = this ;
me . dateField . setMinValue ( date );
},
/**
* Replaces any existing {@link #maxValue} with the new value and refreshes the Date picker.
* @param {Date} value The maximum date that can be selected
*/
setMaxValue : function ( date ){
var me = this ;
me . dateField . setMaxValue ( date );
},
validate : function (){
var me = this ;
return me . dateField . validate ();
}
});