tempusdominus / bootstrap-4

Tempus Dominus Bootstrap 4 Datetime Picker
https://getdatepicker.com/5-4/
MIT License
609 stars 238 forks source link

Add sample binding handler for knockoutjs #183

Open brettryan opened 6 years ago

brettryan commented 6 years ago

A binding handler that I've been using which seems to work well is as follows:

ko.bindingHandlers.dateTimePicker = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var options = allBindingsAccessor().dateTimePickerOptions || {};
    var initialValue = ko.utils.unwrapObservable(valueAccessor());
    if (initialValue) {
      options.date = initialValue;
    }
    $(element).datetimepicker(options);

    ko.utils.registerEventHandler(element, "change.datetimepicker", function (event) {
      var value = valueAccessor();
      if (ko.isObservable(value)) {
        value(event.date || null);
      }
    });

    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
      $(element).datetimepicker("destroy");
    });
  },
  update: function (element, valueAccessor) {
    var val = ko.utils.unwrapObservable(valueAccessor());
    if ($(element).datetimepicker) {
      $(element).datetimepicker("date", val);
    }
  }
};
HarpeyMark commented 5 years ago

The update only gets called during init, after that it no longer works for me. Using jquery, bs4, knockout, tempusdominus.

https://jsfiddle.net/mharmon_surge/0w5pqkds/85/

HarpeyMark commented 5 years ago

For anyone else coming here to find the solution, the mistake I made was adding the data-bind attribute to the input control instead of the parent div control. See: https://jsfiddle.net/mharmon_surge/0w5pqkds/ and https://stackoverflow.com/questions/56419064/tempusdominus-knockout-binding-doesnt-fire-update-event-after-initializing

thedwillis commented 5 years ago

Hi Mark, your fiddle link is now broken. and your post on stack overflow links to a fiddle with a solution using a different library. Do you still have a working version of the tempus dominus binding you could share? Specifically I am struggling with accessing the child input element's value when the binding is applied to the parent div. Thanks!

MrModeus commented 5 years ago

Hi Mark, your fiddle link is now broken. and your post on stack overflow links to a fiddle with a solution using a different library. Do you still have a working version of the tempus dominus binding you could share? Specifically I am struggling with accessing the child input element's value when the binding is applied to the parent div. Thanks!

My solution ended up not working.

dove commented 4 years ago

I've got binding working when using interface. However, trying to edit the time by hand in the input I get this._getLastPickedDate(...) is undefined as field value is made null. Debugging my handler shows the value to be null from change. Can anyone else edit time or date directly typing in the input box?

malbert69 commented 4 years ago

The following edit works for me with both the calendar AND manual editing of the text input. I added || target.input.value to the "change.datetimepicker" event.

ko.bindingHandlers.dateTimePicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().dateTimePickerOptions || {};
        var initialValue = ko.utils.unwrapObservable(valueAccessor());
        if (initialValue) {
            options.date = initialValue;
        }
        $(element).datetimepicker(options);

        ko.utils.registerEventHandler(element, "change.datetimepicker", function (event) {
            var value = valueAccessor();
            if (ko.isObservable(value)) {
                value(event.date || event.target.value || null);
            }
        });

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).datetimepicker("destroy");
        });
    },
    update: function (element, valueAccessor) {
        var val = ko.utils.unwrapObservable(valueAccessor());
        console.log(arguments, val);
        if ($(element).datetimepicker) {
            $(element).datetimepicker("date", val);
        }
    }
};