Friday, July 8, 2016

Knockout + Kendo UI Date Picker - Open To Specific Date without Selecting

Don't you just love working with 3rd party vendor controls? In this post, I want to look at how you can open a Kendo UI Date Picker to a specific date, without selecting the date.

The Problem

Let's say you are using Knockout with Kendo UI and the Knockout-Kendo bindings. Your view model has two properties, one for start date and one for end date.

class DateRange {
    start: KnockoutObservable;
    end: KnockoutObservable;  // end date is optional

    constructor(start?: Date, end?: Date){
        this.start = ko.observable(start);
        this.end = ko.observable(end);
    }
}


When the user selects a start date in the future (more specifically, a start date that requires calendar paging), then we want the end date calendar to open to the same date, but not select the end date because the end date is optional.

The following code does not work correctly. It seems that setting the value of the DateView does not set the value of the observable property bound to the calendar and you cannot re-select the selected date. Consider the following steps:
  1. Select Start Date of July 10th, 2016
  2. Open End Date Calendar; notice that July 10th is selected, but the DateRange.end observable is not set
  3. Attempt to select July 10th for end date; nothing happens

// DOES NOT WORK
<input class="form-control" data-bind="kendoDatePicker: { value: start, min: new Date() }" placeholder="Start Date* (mm/dd/yyyy)" />
<input class="form-control" data-bind="kendoDatePicker: { 
    value: end,
    min: new Date(),
    open: function(e){
        if(start() && !end()) {
            e.sender.dateView.value(start());
        }
    }
}" placeholder="End Date* (mm/dd/yyyy)" />


By setting the value to the desired date and back to null, the date becomes focused, but not selected. This allows re-selection of that date.

// WORKS - null out value again; it keeps focus but is not selected
<input class="form-control" data-bind="kendoDatePicker: { value: start, min: new Date() }" placeholder="Start Date* (mm/dd/yyyy)" />
<input class="form-control" data-bind="kendoDatePicker: {
    value: end,
    min: new Date(),
    open: function(e){
        if(start() && !end()) { 
            e.sender.dateView.value(start());
            e.sender.dateView.value(null);
        }
    }
}" placeholder="End Date* (mm/dd/yyyy)" />