knockoutjs databind with jquery-ui datepicker

Rasmus Christensen picture Rasmus Christensen · Jun 18, 2011 · Viewed 40.9k times · Source

I'm using a jQuery UI datepicker. The HTML input field behind it is currently hooked up to KnockoutJS as a dependentObservable, but when its value is set in the viewmodel, the datepicker loses its format.

How should I do this and not lose the format? I would like the viewModel not to know that it is a jQuery datepicker.

Answer

RP Niemeyer picture RP Niemeyer · Jun 19, 2011

You could write a custom binding that sets the date in the field using the datepicker APIs and also sets the value of your observable by reading the date properly.

The custom binding might look like:

ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().datepickerOptions || {},
            $el = $(element);

        //initialize datepicker with some optional options
        $el.datepicker(options);

        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function() {
            var observable = valueAccessor();
            observable($el.datepicker("getDate"));
        });

        //handle disposal (if KO removes by the template binding)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $el.datepicker("destroy");
        });

    },
    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            $el = $(element),
            current = $el.datepicker("getDate");

        if (value - current !== 0) {
            $el.datepicker("setDate", value);   
        }
    }
};

You would use it like:

<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />

The datepickeroptions would be optional and could include anything that you want to pass into the datepicker() call.

Also, this assumes that you are using an observable for the date. The binding has to do a little more work if you want to do a one-way binding with a non-observable, but that is unlikely.

Sample here: http://jsfiddle.net/rniemeyer/NAgNV/