Recently, I have been given a task to make extjs datepicker allowing for selection of multiple dates. Unfortunately afters hours of searching for some build-in function, it turned out that this kind of functionality is not supported by default. Finaly, I decided to extend datepicker by creating component called highlightableDatePicker. I started from creating a class which inhierits from Ext.picker.Date. First draft of class looked this way
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Ext.define('HighlightableDatePicker', { extend: 'Ext.picker.Date', selectedDates:{}, clsHighlightClass:'x-datepicker-selected', initComponent: function(){ var me = this; me.callParent(arguments); }, highlightDates: function(){ var me = this; } }) |
In this class I created additional function highlightDates which is responsible for highlighting dates. Moreover, I added some additional config elements:
- selectedDates – object keeping track of dates which should be selected
- clsHighlightClass – css class defining selected cell style
The most important part of HighlightableDatepicker class is function highlightDates which is responsible for highlighting dates. The body of this method looks like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
highlightDates: function(){ var me = this; if(!me.cells) return; me.cells.each(function(item){ var date = new Date(item.dom.firstChild.dateValue).toDateString(); if(me.selectedDates[date]){ if(item.getAttribute('class').indexOf(me.clsHighlightClass)=== -1){ item.addCls(me.clsHighlightClass) } }else{ item.removeCls(me.clsHighlightClass); } }) } |
As You can see, this function simply compares date in cell with dates stored in selectedDates. If there is a match, cell style is modified by adding extra CSS class into class attribute of cell (see addCls function of Extjs), otherwise CSS class responsible for highlighting is removed. Having defind highlightDates function,I also had to attach an event handler to select event, in order to modify collection of selected dates. This handler looks this way
1 2 3 4 5 6 7 8 |
handleSelectionChanged: function(cmp, date){ var me = this; if(me.selectedDates[date.toDateString()]) delete me.selectedDates[date.toDateString()] else me.selectedDates[date.toDateString()] = date; me.highlightDates(); } |
The final step to make this control work is to attach event handlers and call highlightDates function during initialization of component.
1 2 3 4 5 6 |
initComponent: function() { var me = this; me.callParent(arguments); me.on('select',me.handleSelectionChanged,me); me.on('afterrender',me.highlightDates,me); } |
Please, notice that highlightDates is called after component is rendered, because there is no rendered cells before that moment. Entire code listing is presented below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
Ext.define('HighlightableDatePicker', { extend: 'Ext.picker.Date', selectedDates : {}, clsHighlightClass :'x-datepicker-selected', initComponent: function(){ var me = this; me.callParent(arguments); me.on('select',me.handleSelectionChanged,me); me.on('afterrender',me.highlightDates,me); }, highlightDates: function(){ var me = this; if(!me.cells) return; me.cells.each(function(item){ var date = new Date(item.dom.firstChild.dateValue).toDateString(); if(me.selectedDates[date]){ if(item.getAttribute('class').indexOf(me.clsHighlightClass)=== -1){ item.addCls(me.clsHighlightClass) } }else{ item.removeCls(me.clsHighlightClass); } }) }, handleSelectionChanged: function(cmp, date){ var me = this; if(me.selectedDates[date.toDateString()]) delete me.selectedDates[date.toDateString()] else me.selectedDates[date.toDateString()] = date; me.highlightDates(); } }) |
and the result
Source code for this post can be found here