Range Sliders for Dates and Times using Kendo UI
Ever needed to create one of those range-style sliders for Dates or Times? Like what you might see when selecting flight times for airline tickets — show me flights that take off after 7am, but before 12pm, thanks! You can do something similar with the Kendo UI RangeSlider widget. But let me point out a few tips to help.
Normally I like to use declarative initialization whenever possible, especially when I am using MVVM binding anyway. But in this case, not everything you need can be done declaratively. But that’s ok.
First, let’s start with a Time slider. We need to bind the numeric part of the slider to the milliseconds of the time, so I’ll save you a little math. Here is how to create a range slider for a 24 hour period. Yes, we can do most of this declaratively.
A range slider requires a div and two input elements, as shown below. Also, note that the value will be an array with two items, the min and max selection. I have set my step size to be one hour. Also, I have set the tooltip to display the values formatted as times.
<div id="timeSlider" data-bind="value: selectedTimeRange" data-role="rangeslider" data-small-step="3600000" data-min="21600000" data-max="108000000" data-large-step="3600000" data-tickplacement="none" data-tooltip="{
template:'#=kendo.toString(new Date(selectionStart), \'h:mm tt\' ) # to #=kendo.toString(new Date(selectionEnd), \'h:mm tt\' ) #'
}" >
<input />
<input />
</div>
Displaying labels on the tick marks doesn’t really work too well, so instead we can hide the tick labels altogether with a little CSS:
.k-tick > .k-label{
display: none;
}
And finally, we can display the values below the slider using Kendo MVVM and the following function.
timeRangeChanged: function(){
var timeRange = viewModel.selectedTimeRange;
var startTime = kendo.toString(new Date(timeRange[0]), 'h:mm tt' );
var endTime = kendo.toString(new Date(timeRange[1]), 'h:mm tt' );
viewModel.set('hoursStart', startTime);
viewModel.set('hoursEnd', endTime);
},
Now, after understanding how all of those pieces fit together, we can start on the date range slider. I added two DatePicker widgets to set the start and end DateTime values, but here’s the tricky part. In order to change the options of the Kendo UI RangeSlider, we have to recreate the entire widget. It’s not my favorite solution, but it is functional!
updateDateSlider: function(){
if ( viewModel.selectedStartDate <= viewModel.selectedEndDate)
{
// reinitialize the date slider, since sliders do not support dynamic changes
var slider = $("#dateSlider").data("kendoRangeSlider");
if (slider){
var wrapper = slider.wrapper;
var element = slider.element;
slider.destroy();
wrapper.before(element.show());
wrapper.remove();
}
$("#dateSlider").kendoRangeSlider({
largeStep: 86400000,
smallStep: 86400000,
min: viewModel.selectedStartDate.getTime(),
max: viewModel.selectedEndDate.getTime(),
value: [viewModel.selectedStartDate.getTime(), viewModel.selectedEndDate.getTime()],
tooltip: {
template: kendo.template('#=kendo.toString(new Date(selectionStart), \'M/d/yyyy\' ) # to #=kendo.toString(new Date(selectionEnd), \'M/d/yyyy\' ) #')
},
change: viewModel.dateRangeChanged
});
viewModel.resizeSliders();
viewModel.dateRangeChanged();
}
},
And finally, one more tip. To get the RangeSliders to expand to fill the width of their container, we have to do a little more manipulation. I call this function after initialization, but you may also want to use it for window resizing.
resizeSliders: function(){
// resize the sliders to fill the container
var sliders = $("[data-role='rangeslider']");
sliders.each(function (index, ele) {
var slider = $(ele).getKendoRangeSlider();
slider.wrapper.css("width", "100%");
slider.resize();
});
}
So, here’s how it looks altogether.