Page 1 of 3 123 LastLast
Results 1 to 10 of 22

Thread: Extend Date Picker for DateTimePicker but problem with numberfield not editable

  1. #1
    Sencha User
    Join Date
    Mar 2013
    Posts
    33
    Answers
    2

    Default Answered: Extend Date Picker for DateTimePicker but problem with numberfield not editable

    Hi,

    I recently just extended Date Picker to include 3 numberfield for time selection.
    However, having problem on the time numberfield being not editable and also not clickable on the spinner.
    Once I clicked, the date picker is hidden.

    Attached sample Date Time Picker and Date Time field.

    Please do enlighten me where I got it wrong.

    Sencha Fiddle Code Here
    https://fiddle.sencha.com/#fiddle/tc3



    Date Time Picker
    Code:
    Ext.define('sys.ext.picker.DateTime', {
      extend: 'Ext.picker.Date',
      alias: 'widget.sysdatetimepicker',
      okText: 'OK',
      
      renderTpl: [
        '<div id="{id}-innerEl" data-ref="innerEl" role="presentation">',
          '<div class="{baseCls}-header">',
            '<div id="{id}-prevEl" data-ref="prevEl" class="{baseCls}-prev {baseCls}-arrow" role="presentation" title="{prevText}"></div>',
            '<div id="{id}-middleBtnEl" data-ref="middleBtnEl" class="{baseCls}-month" role="heading">{%this.renderMonthBtn(values, out)%}</div>',
            '<div id="{id}-nextEl" data-ref="nextEl" class="{baseCls}-next {baseCls}-arrow" role="presentation" title="{nextText}"></div>',
          '</div>',
          '<table role="grid" id="{id}-eventEl" data-ref="eventEl" class="{baseCls}-inner" cellspacing="0" tabindex="0">',
              '<thead>',
                  '<tr role="row">',
                      '<tpl for="dayNames">',
                          '<th role="columnheader" class="{parent.baseCls}-column-header" aria-label="{.}">',
                              '<div role="presentation" class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',
                          '</th>',
                      '</tpl>',
                  '</tr>',
              '</thead>',
              '<tbody>',
                  '<tr role="row">',
                      '<tpl for="days">',
                          '{#:this.isEndOfWeek}',
                          '<td role="gridcell">',
                              '<div hidefocus="on" class="{parent.baseCls}-date"></div>',
                          '</td>',
                      '</tpl>',
                  '</tr>',
              '</tbody>',
          '</table>',
          
          '<center>',
          '<table id="{id}-timeEl" style="width: auto; margin-left: 15px; margin-right: 15px; margin-top: 4px; margin-bottom: 4px;" class="x-datepicker-inner" cellspacing="0">',
            '<tbody>',
              '<tr>',
                '<td>{%this.renderHourBtn(values,out)%}</td>',
                '<td style="width: 10px; text-align: center; font-weight: bold;">:</td>',
                '<td>{%this.renderMinuteBtn(values,out)%}</td>',
                '<td style="width: 10px; text-align: center; font-weight: bold;">:</td>',
                '<td>{%this.renderSecondBtn(values,out)%}</td>',
              '</tr>',
            '</tbody>',
          '</table>',
          '</center>',
          
          '<tpl if="showToday">',
              '<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">{%this.renderOkBtn(values, out)%}{%this.renderTodayBtn(values, out)%}</div>',
          '</tpl>',
          // These elements are used with Assistive Technologies such as screen readers
          '<div id="{id}-todayText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{todayText}.</div>',
          '<div id="{id}-ariaMinText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMinText}.</div>',
          '<div id="{id}-ariaMaxText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMaxText}.</div>',
          '<div id="{id}-ariaDisabledDaysText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDaysText}.</div>',
          '<div id="{id}-ariaDisabledDatesText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDatesText}.</div>',
        '</div>',
        {
          firstInitial: function(value) {
            return Ext.picker.Date.prototype.getDayInitial(value);
          },
          
          isEndOfWeek: function(value) {
            // convert from 1 based index to 0 based
            // by decrementing value once.
            value--;
            var end = value % 7 === 0 && value !== 0;
            return end ? '</tr><tr role="row">' : '';
          },
          
          renderTodayBtn: function(values, out) {
            Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out);
          },
          
          renderMonthBtn: function(values, out) {
            Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out);
          },
          
          renderHourBtn: function(values, out) {
            Ext.DomHelper.generateMarkup(values.$comp.hourBtn.getRenderTree(), out);
          },
          
          renderMinuteBtn: function(values, out) {
            Ext.DomHelper.generateMarkup(values.$comp.minuteBtn.getRenderTree(), out);
          },
          
          renderSecondBtn: function(values, out) {
            Ext.DomHelper.generateMarkup(values.$comp.secondBtn.getRenderTree(), out);
          },
          
          renderOkBtn: function(values, out) {
            Ext.DomHelper.generateMarkup(values.$comp.okBtn.getRenderTree(), out);
          }
        }
      ],
      
      beforeRender: function() {
        var me = this, _$Number = Ext.form.field.Number, today = Ext.Date.format(new Date(), me.format);
        
        me.hourBtn = new _$Number({
          minValue: 0 ,
          maxValue: 23,
          step: 1,
          width: 68,
          align: 'right'
        });
        
        me.minuteBtn = new _$Number({
          minValue: 0,
          maxValue: 59,
          step: 1,
          width: 68
        });
        
        me.secondBtn = new _$Number({
          minValue: 0,
          maxValue: 59,
          step: 1,
          width: 68
        });
        
        me.okBtn = new Ext.button.Button({
          ui: me.footerButtonUI,
          ownerCt: me,
          ownerLayout: me.getComponentLayout(),
          text: me.okText,
          tooltipType: 'title',
          tabIndex: -1,
          ariaRole: 'presentation',
          handler: me.okHandler,
          scope: me
        });
        
        me.callParent();
      },
      
      privates : {
        finishRenderChildren: function() {
          var me = this;
          me.callParent();
          
          me.hourBtn.finishRender();
          me.minuteBtn.finishRender();
          me.secondBtn.finishRender();
          me.okBtn.finishRender();
        }
      },
      
      okHandler: function() {
        var me = this, btn = me.okBtn;
    
        if(btn && !btn.disabled) {
          me.setValue(this.getValue());
          me.fireEvent('select', me, me.value);
          me.onSelect();
        }
        
        return me;
      },
      
      selectedUpdate: function(date) {
        this.callParent([Ext.Date.clearTime(date, true)]);
      },
      
      update: function(date, forceRefresh) {
        var me = this;
        
        me.hourBtn.setValue(date.getHours());
        me.minuteBtn.setValue(date.getMinutes());
        me.secondBtn.setValue(date.getSeconds());
        
        return this.callParent(arguments);
      },
      
      setValue: function(date, isFixed) {
        var me = this;
        
        if(isFixed !== true) {
          date.setHours(me.hourBtn.getValue());
          date.setMinutes(me.minuteBtn.getValue());
          date.setSeconds(me.secondBtn.getValue());
        }
        
        me.value = date;
        me.update(me.value);
        
        return me;
      },
      
      // @private
      // @inheritdoc
      beforeDestroy: function() {
        var me = this;
    
        if(me.rendered) {
          Ext.destroy(
            me.hourBtn,
            me.minuteBtn,
            me.secondBtn,
            me.okBtn
          );
        }
      
        me.callParent();
      },
      
      handleDateClick: function(e, t) {
        var me = this, handler = me.handler;
    
        e.stopEvent();
        
        if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
          me.doCancelFocus = me.focusOnSelect === false;
          me.setValue(new Date(t.dateValue));
          delete me.doCancelFocus;
          
          /* by pass on select to keep the window open
          me.fireEvent('select', me, me.value);
          if (handler) {
              handler.call(me.scope || me, me, me.value);
          }
          // event handling is turned off on hide
          // when we are using the picker in a field
          // therefore onSelect comes AFTER the select
          // event.
          me.onSelect();
          */
        }
      }
    });

    Date Time field
    Code:
    Ext.define('sys.ext.form.field.DateTime', {
      extend:'Ext.form.field.Date',
      alias: 'widget.sysdatetimefield',
      requires: ['sys.ext.picker.DateTime'],
      
      format : "m/d/Y H:i:s",
      
      altFormats : "m/d/Y H:i:s",
      
      createPicker: function() {
        var me = this, format = Ext.String.format;
        
        return new sys.ext.picker.DateTime({
          pickerField: me,
          floating: true,
          preventRefocus: true,
          hidden: true,
          minDate: me.minValue,
          maxDate: me.maxValue,
          disabledDatesRE: me.disabledDatesRE,
          disabledDatesText: me.disabledDatesText,
          ariaDisabledDatesText: me.ariaDisabledDatesText,
          disabledDays: me.disabledDays,
          disabledDaysText: me.disabledDaysText,
          ariaDisabledDaysText: me.ariaDisabledDaysText,
          format: me.format,
          showToday: me.showToday,
          startDay: me.startDay,
          minText: format(me.minText, me.formatDate(me.minValue)),
          ariaMinText: format(me.ariaMinText, me.formatDate(me.minValue, me.ariaFormat)),
          maxText: format(me.maxText, me.formatDate(me.maxValue)),
          ariaMaxText: format(me.ariaMaxText, me.formatDate(me.maxValue, me.ariaFormat)),
          
          listeners: {
            scope: me,
            select: me.onSelect
          },
          keyNavConfig: {
            esc: function() {
              me.inputEl.focus();
              me.collapse();
            }
          }
        });
      },
      
      onExpand: function() {
        var value = this.getValue();
        this.picker.setValue(Ext.isDate(value) ? value : new Date(), true);
      }
    });
    Sample Output
    2015-09-03_224640.png

  2. Managed to solve it after studying ExtJS source code.
    I updated my Sencha Fiddle to make it work.
    Basically, the hack is on the picker, onMouseDown() function.
    Because of it prevent all default events on mouse down, so it cancel all the events and make those textfield / numberfield you used for the time not functioning.
    Hence, I check the targetId, and do nothing (aka do not prevent defaults) when it is numberfield.

    Updated Sencha Fiddle at:
    https://fiddle.sencha.com/#fiddle/tc3

  3. #2
    Sencha - Support Team
    Join Date
    Mar 2015
    Location
    Chicago
    Posts
    239
    Answers
    40

    Default

    Hi,

    You need to add an ownerCt and ownerLayout to your new components and also add them to the getRefItems method.

    Check this fork of your fiddle: https://fiddle.sencha.com/#fiddle/tso
    Guilherme Lopes
    Sencha Support

  4. #3
    Sencha User
    Join Date
    Mar 2013
    Posts
    33
    Answers
    2

    Default

    Thanks for your feedback.
    I still found a problem, why when I click on the textbox, it cannot be focused.
    It only focused once I click on the up down arrow ?
    Any solution for that ?

  5. #4
    Sencha User
    Join Date
    Jan 2015
    Location
    Vancouver
    Posts
    15

    Default

    I am experiencing exactly same behaviour.
    Did anyone find a solution/workaround?

  6. #5
    Sencha Premium User
    Join Date
    Jan 2008
    Location
    Germany
    Posts
    538
    Answers
    1

    Default

    To make the number fields focusable, the picker's onMouseDown handler handler needs to be overridden to let the mouse event pass for input controls.
    Also there were still a few bits and pieces missing from the code to make the component integrate with standard framework behavior, especially in regards to keyboard event handling. I adjusted where I felt it makes sense, sharing the code below.

    Thanks @deathgod86 for sharing the original code. Treating time selection with spinner fields is much more intuitive IMHO than the slider-based solution that's been around for a while now.
    So here's the code:

    Date/time field
    Code:
    Ext.define('Ext.ux.form.field.DateTime', {
    
        extend: 'Ext.form.field.Date',
        alias: 'widget.datetimefield',
        requires: [
            'Ext.ux.picker.DateTime'
        ],
    
        format: "m/d/Y g:i:s A",
        ariaFormat: 'M j Y, g:i:s A',
        altFormats: "m/d/Y g:i:s A",
    
        createPicker: function() {
    
            var me = this,
                format = Ext.String.format;
    
            return new Ext.ux.picker.DateTime({
                pickerField: me,
                floating: true,
                preventRefocus: true,
                hidden: true,
                minDate: me.minValue,
                maxDate: me.maxValue,
                disabledDatesRE: me.disabledDatesRE,
                disabledDatesText: me.disabledDatesText,
                ariaDisabledDatesText: me.ariaDisabledDatesText,
                disabledDays: me.disabledDays,
                disabledDaysText: me.disabledDaysText,
                ariaDisabledDaysText: me.ariaDisabledDaysText,
                format: me.format,
                showToday: me.showToday,
                startDay: me.startDay,
                minText: format(me.minText, me.formatDate(me.minValue)),
                ariaMinText: format(me.ariaMinText, me.formatDate(me.minValue, me.ariaFormat)),
                maxText: format(me.maxText, me.formatDate(me.maxValue)),
                ariaMaxText: format(me.ariaMaxText, me.formatDate(me.maxValue, me.ariaFormat)),
                listeners: {
                    scope: me,
                    select: me.onSelect
                },
                keyNavConfig: {
                    esc: function() {
                        me.inputEl.focus();
                        me.collapse();
                    }
                }
            });
        },
    
        onExpand: function() {
            var value = this.getValue();
            this.picker.setValue(Ext.isDate(value) ? value : new Date());
        }
    
    });
    Date/time picker
    Code:
    Ext.define('Ext.ux.picker.DateTime', {
    
        extend: 'Ext.picker.Date',
        alias: 'widget.datetimepicker',
    
        okText: 'OK',
    
        focusable: true,
    
        renderTpl: [
            '<div id="{id}-innerEl" data-ref="innerEl" role="presentation">',
                '<div class="{baseCls}-header">',
                    '<div id="{id}-prevEl" data-ref="prevEl" class="{baseCls}-prev {baseCls}-arrow" role="presentation" title="{prevText}"></div>',
                    '<div id="{id}-middleBtnEl" data-ref="middleBtnEl" class="{baseCls}-month" role="heading">{%this.renderMonthBtn(values, out)%}</div>',
                    '<div id="{id}-nextEl" data-ref="nextEl" class="{baseCls}-next {baseCls}-arrow" role="presentation" title="{nextText}"></div>',
                '</div>',
                '<table role="grid" id="{id}-eventEl" data-ref="eventEl" class="{baseCls}-inner" cellspacing="0" tabindex="0" aria-readonly="true">',
                    '<thead>',
                        '<tr role="row">',
                            '<tpl for="dayNames">',
                                '<th role="columnheader" class="{parent.baseCls}-column-header" aria-label="{.}">',
                                    '<div role="presentation" class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',
                                '</th>',
                            '</tpl>',
                        '</tr>',
                    '</thead>',
                    '<tbody>',
                        '<tr role="row">',
                            '<tpl for="days">',
                                '{#:this.isEndOfWeek}',
                                '<td role="gridcell">',
                                    '<div hidefocus="on" class="{parent.baseCls}-date"></div>',
                                '</td>',
                            '</tpl>',
                        '</tr>',
                    '</tbody>',
                '</table>',
                '<div style="text-align: center">',
                    '<table id="{id}-timeEl" data-ref="timeEl" style="margin: 4px auto" class="{baseCls}-datepicker-inner" cellspacing="0">',
                        '<tbody>',
                            '<tr>',
                                '<td>{%this.renderHourFld(values, out)%}</td>',
                                '<td style="padding: 0 5px">:</td>',
                                '<td>{%this.renderMinuteFld(values, out)%}</td>',
                                '<td style="padding: 0 5px">:</td>',
                                '<td>{%this.renderSecondFld(values, out)%}</td>',
                            '</tr>',
                        '</tbody>',
                    '</table>',
                '</div>',
                '<tpl if="showToday">',
                    '<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">{%this.renderOkBtn(values, out)%}{%this.renderTodayBtn(values, out)%}</div>',
                '</tpl>',
                // These elements are used with Assistive Technologies such as screen readers
                '<div id="{id}-todayText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{todayText}.</div>',
                '<div id="{id}-ariaMinText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMinText}.</div>',
                '<div id="{id}-ariaMaxText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMaxText}.</div>',
                '<div id="{id}-ariaDisabledDaysText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDaysText}.</div>',
                '<div id="{id}-ariaDisabledDatesText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDatesText}.</div>',
            '</div>',
            {
                firstInitial: function(value) {
                    return Ext.picker.Date.prototype.getDayInitial(value);
                },
                isEndOfWeek: function(value) {
                    // Convert from 1-based index to 0-based by decrementing value once.
                    value--;
                    var end = value % 7 === 0 && value !== 0;
                    return end ? '</tr><tr role="row">' : '';
                },
                renderTodayBtn: function(values, out) {
                    Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out);
                },
                renderMonthBtn: function(values, out) {
                    Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out);
                },
                renderHourFld: function(values, out) {
                    Ext.DomHelper.generateMarkup(values.$comp.hourFld.getRenderTree(), out);
                },
                renderMinuteFld: function(values, out) {
                    Ext.DomHelper.generateMarkup(values.$comp.minuteFld.getRenderTree(), out);
                },
                renderSecondFld: function(values, out) {
                    Ext.DomHelper.generateMarkup(values.$comp.secondFld.getRenderTree(), out);
                },
                renderOkBtn: function(values, out) {
                    Ext.DomHelper.generateMarkup(values.$comp.okBtn.getRenderTree(), out);
                }
            }
        ],
    
        beforeRender: function() {
    
            var me = this;
    
            var numberFldBaseCfg = {
                minValue: 0,
                allowDecimals: false,
                autoStripChars: true,
                width: 80,
                fieldStyle: 'text-align: right',
                ownerCt: me,
                ownerLayout: me.getComponentLayout()
            };
            me.hourFld = new Ext.form.field.Number(Ext.apply({}, numberFldBaseCfg, {
                maxValue: 23
            }));
            me.minuteFld = new Ext.form.field.Number(Ext.apply({}, numberFldBaseCfg, {
                maxValue: 59
            }));
            me.secondFld = new Ext.form.field.Number(Ext.apply({}, numberFldBaseCfg, {
                maxValue: 59
            }));
    
            me.okBtn = new Ext.button.Button({
                ui: me.footerButtonUI,
                ownerCt: me,
                ownerLayout: me.getComponentLayout(),
                text: me.okText,
                tooltipType: 'title',
                tabIndex: -1,
                ariaRole: 'presentation',
                handler: me.onOkClickMain,
                scope: me
            });
    
            me.callParent(arguments);
    
        },
    
        getRefItems: function() {
    
            var results = [],
                monthBtn = this.monthBtn,
                todayBtn = this.todayBtn,
                hourFld = this.hourFld,
                minuteFld = this.minuteFld,
                secondFld = this.secondFld,
                okBtn = this.okBtn;
    
            if (monthBtn) {
                results.push(monthBtn);
            }
            if (todayBtn) {
                results.push(todayBtn);
            }
            if (hourFld) {
                results.push(hourFld);
            }
            if (minuteFld) {
                results.push(minuteFld);
            }
            if (secondFld) {
                results.push(secondFld);
            }
            if (okBtn) {
                results.push(okBtn);
            }
    
            return results;
    
        },
    
        privates: {
    
            finishRenderChildren: function() {
                var me = this;
                me.callParent(arguments);
                me.hourFld.finishRender();
                me.minuteFld.finishRender();
                me.secondFld.finishRender();
                me.okBtn.finishRender();
            }
    
        },
    
        onOkClickMain: function() {
            var me = this,
                btn = me.okBtn,
                handler = me.handler;
            if (btn && !btn.disabled) {
                me.setValue(this.getValue(), true);
                me.fireEvent('select', me, me.value);
                if (handler) {
                    handler.call(me.scope || me, me, me.value);
                }
                me.onSelect();
            }
            return me;
        },
    
        onOkClick: function(picker, value) { // Month picker!
            var me = this,
                month = value[0],
                year = value[1],
                date = new Date(year, month, me.getActive().getDate());
            if (date.getMonth() !== month) {
                date = Ext.Date.getLastDateOfMonth(new Date(year, month, 1));
            }
            me.setValue(date, true);
            me.hideMonthPicker();
        },
    
        selectedUpdate: function(date) {
            this.callParent([Ext.Date.clearTime(date, true)]);
        },
    
        update: function(date, forceRefresh) {
            var me = this;
            me.hourFld.setValue(date.getHours());
            me.minuteFld.setValue(date.getMinutes());
            me.secondFld.setValue(date.getSeconds());
            return this.callParent(arguments);
        },
    
        setValue: function(date, applyTime) {
            var me = this;
            if (applyTime === true) {
                date.setHours(me.hourFld.getValue());
                date.setMinutes(me.minuteFld.getValue());
                date.setSeconds(me.secondFld.getValue());
            }
            me.value = date;
            return me.update(me.value);
        },
    
        beforeDestroy: function() {
            var me = this;
            if (me.rendered) {
                Ext.destroy(me.hourFld, me.minuteFld, me.secondFld, me.okBtn);
            }
            me.callParent(arguments);
        },
    
        selectToday: function() {
            var me = this,
                btn = me.todayBtn;
            if (btn && !btn.disabled) {
                me.setValue(new Date(), true);
            }
            return me;
        },
    
        onMouseDown: function(evt) {
            if (!evt.getTarget('input')) evt.preventDefault();
        },
    
        handleDateClick: function(evt, domEl) {
            var me = this,
                handler = me.handler;
            evt.stopEvent();
            if (!me.disabled && domEl.dateValue && !Ext.fly(domEl.parentNode).hasCls(me.disabledCellCls)) {
                me.setValue(new Date(domEl.dateValue), true);
                if (evt.getKey() === evt.ENTER) {
                    if (handler) {
                        handler.call(me.scope || me, me, me.value);
                    };
                    me.onSelect();
                }
            }
        },
    
        handleTabKey: Ext.emptyFn // We don't want to collapse the picker on tab, cycle to time input fields instead
    
    });

  7. #6
    Ext JS Premium Member
    Join Date
    Aug 2007
    Location
    Sarnia, ON, Canada
    Posts
    62

    Default

    Quote Originally Posted by Stefan B View Post
    To make the number fields focusable, the picker's onMouseDown handler handler needs to be overridden to let the mouse event pass for input controls.
    Also there were still a few bits and pieces missing from the code to make the component integrate with standard framework behavior, especially in regards to keyboard event handling. I adjusted where I felt it makes sense, sharing the code below.

    Thanks @deathgod86 for sharing the original code. Treating time selection with spinner fields is much more intuitive IMHO than the slider-based solution that's been around for a while now.

    ...
    Thanks for sharing your fixes. I had a couple small issues with the code though. Here is the fiddle with fixes: https://fiddle.sencha.com/#fiddle/1cl2

    I am disappointed that we have to go through such lengths to implement this. Of all the amazing features in ExtJS why would they design a control that that populates half of a date object? This just seems like such a no brainer config option that should exist by default .

  8. #7
    Sencha - Support Team
    Join Date
    Mar 2015
    Location
    Chicago
    Posts
    239
    Answers
    40

    Default

    ExtJS is extensible, so you can you develop your own components if you need to.
    I developed a UX for DateTimeField a while ago, see here: https://github.com/gportela85/DateTimeField

    Some people don't like the Sliders approach so they can develop their own field with spinners, or comboboxes, or whatever they like.
    Guilherme Lopes
    Sencha Support

  9. #8
    Ext JS Premium Member
    Join Date
    Aug 2007
    Location
    Sarnia, ON, Canada
    Posts
    62

    Thumbs up

    Quote Originally Posted by guilherme.lopes View Post
    ExtJS is extensible, so you can you develop your own components if you need to.
    I developed a UX for DateTimeField a while ago, see here: https://github.com/gportela85/DateTimeField

    Some people don't like the Sliders approach so they can develop their own field with spinners, or comboboxes, or whatever they like.
    I completely understand your point of view. But I think that populating a date object with a date and time is so fundamental that I am certain that, if Sencha implemented a date control with a time option, most developers would accept Sencha's implementation and save themselves the hassle of reinventing the wheel. To me, a datetime picker is the same if not more common than say Ext.toast in terms of UX agnostics / extensibility. Yet we have light weight implementation of toasts which used to be a community Ext.UX in earlier versions.

    Nevertheless, big thanks to guys like you (@guilherme.lopes) and @deathgod86 for providing this to the community. It works great!

  10. #9
    Sencha Premium User
    Join Date
    Jan 2008
    Location
    Germany
    Posts
    538
    Answers
    1

    Default

    @ milanz,

    apart from the classpath of the date picker that I didn't adjust before pasting the code here (fixed above), and the changed default width for the time spinners, were there any other issues? I'd like to avoid them too in my app obviously but were not able to spot any more diffs between your fiddle and my code.


    @ guilherme.lopez,

    I also do see the point, ExtJS' extensibility is really what makes the framework of choise for large enterprise applications. The thing is, not all components are equally easy to extend. In the case of the date/time picker, you have to fiddle with the rendering template, and this is what makes it really awkward because the DOM is the part that's usually the least stable across framework updates.

  11. #10
    Sencha User
    Join Date
    Apr 2013
    Posts
    913
    Answers
    105

    Default

    Quote Originally Posted by Stefan B View Post
    In the case of the date/time picker, you have to fiddle with the rendering template, and this is what makes it really awkward because the DOM is the part that's usually the least stable across framework updates.
    You can also do what Guilherme Lopes did in his DateTimeField component - instead of messing with date picker's template, just add a separate picker for hours and minutes next to it.

    BTW, the UX you made doesn't work with Triton, Neptune Touch and Crisp Touch themes. Also, time fields are reset if you use month/year picker.

Page 1 of 3 123 LastLast

Similar Threads

  1. Date picker problem
    By heartlesslove in forum Ext: Q&A
    Replies: 3
    Last Post: 9 Oct 2013, 3:50 AM
  2. problem with date picker
    By lchurch in forum Sencha Touch 2.x: Q&A
    Replies: 2
    Last Post: 1 Apr 2012, 12:06 PM
  3. Date Picker Problem
    By Sameer Khan in forum Sencha Touch 1.x: Q&A
    Replies: 1
    Last Post: 29 Nov 2011, 6:24 AM
  4. Problem Date picker
    By rajakrishnamca in forum Ext 2.x: Help & Discussion
    Replies: 3
    Last Post: 3 Jun 2008, 1:45 AM
  5. Problem with date picker
    By achebv in forum Ext 1.x: Help & Discussion
    Replies: 0
    Last Post: 2 Oct 2007, 12:01 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •