Alex
Alex

Reputation: 38519

Using jQuery UI datepicker with hour / minute dropdowns with KnockoutJS

I've got a view model that looks like this:

var ViewModel = function() {
    var self = this;

    self.hourOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
    self.minuteOptions = [0, 15, 30, 45];

    self.formatTimeOption = function(hour) {
        if (hour < 10) return "0" + hour;
            return hour.toString();
    };

    self.startDate = ko.observable(null);

    self.startDateHour = ko.computed({
        read: function() {
            return new Date(self.startDate()).getHours();
        },
        write: function(value) {
            var newDate = new Date(self.startDate());
            newDate.setHours(value);
            self.startDate(newDate);
        }
    });

    self.startDateMinute = ko.computed({
        read: function() {
            return new Date(self.startDate()).getMinutes();
        },
        write: function(value) {
            var newDate = new Date(self.startDate());
            newDate.setMinutes(value);
            self.startDate(newDate);
        }
    });
};

As you can see, I've got a writeable computed observable that updates the startDate hours / minutes when updated.
This is working, however when it does so, the datepicker input field displays the long form of the date, rather than (for example)

01/03/2013

JSFiddle of this is available here: http://jsfiddle.net/alexjamesbrown/2kSpL/9/

Upvotes: 1

Views: 1390

Answers (1)

Alex
Alex

Reputation: 38519

I solved this by adding the following custom binding handler, as taken from this answer

ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        //initialize datepicker with some optional options
        var options = allBindingsAccessor().datepickerOptions || {};
        $(element).datepicker(options);

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

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

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

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

Here's a working JSFiddle:
http://jsfiddle.net/alexjamesbrown/v6hdS/

Upvotes: 1

Related Questions