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 && 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 && me.submitValue && !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();
}
});