javascriptknockout.jseonasdan-datetimepicker

Knockout bindingHandler with Eonasdan datepicker does not fire dp.change event when selecting date


I'm using Knockout(ver 3.4.2), moment(ver 2.29.1) and Eonasdan datepicker (ver 4.17.47) plugin för selecting dates.

My problem is that the dp.change event is not fired when the user picks a date. It fires when the datepicker/widget is opened, ie the user clicks the calendar-icon.

The result is that the first date the user picks get's ignored (event fires before date is actually picked) and the date is only updated if the user opens the datepicker again and the event fires.

I have been using the knockout bindinghandle example from eonasdans installation page: http://eonasdan.github.io/bootstrap-datetimepicker/Installing/

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

        //when a user changes the date, update the view model
        ko.utils.registerEventHandler(element, "dp.change", function (event) {
            var value = valueAccessor();
            if (ko.isObservable(value)) {
                if (event.date != null && !(event.date instanceof Date)) {
                    value(event.date.toDate());
                } else {
                    value(event.date);
                }
            }
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            var picker = $(element).data("DateTimePicker");
            if (picker) {
                picker.destroy();
            }
        });
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

        var picker = $(element).data("DateTimePicker");
        //when the view model is updated, update the widget
        if (picker) {
            var koDate = ko.utils.unwrapObservable(valueAccessor());

            //in case return from server datetime i am get in this form for example /Date(93989393)/ then fomat this
            //koDate = (typeof (koDate) !== 'object') ? new Date(parseFloat(koDate.replace(/[^0-9]/g, ''))) : koDate;

            picker.date(koDate);
        }
    }
};

And my knockout view looks like this:

var exportLicenserModel = function () {
        var self = this;
        self.Startdatum = ko.observable((new moment()).month(0).date(1));
}

And the HTML is:

<div class='input-group js-date'>
  <input type="text" class="form-control" id="licenseStartDate" data-bind="datepicker: Startdatum, datepickerOptions: { locale: 'sv', format: 'YYYY-MM-DD', useCurrent: false }" />
  <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
</div>

Solution

  • I found the reason why it seemed the dp.change event didn't fire.

    There was a old and obsolete jQuery class in the project that looked up marked datepickers and activated them, making them bind twice.

    $('.js-date').datetimepicker({ locale: 'sv', format: 'YYYY-MM-DD', useCurrent: false });
    

    After removing this, everything worked as expected.