Search code examples
datepickerknockout.jstwitter-bootstrap

Bootstrap datepicker with knockout.js databind


This question is similar to knockoutjs databind with jquery-ui datepicker, but instead of the jQueryUI datepicker, I would like to use one of the Bootstrap datepickers.

The API for the Bootstrap datepicker is different from jquery-ui, and I am having some trouble wrapping my head around making it work with knockout.js. I have created a jsFiddle to try it out.

It seems like the Bootstrap datepicker could be much simpler to use because it does not independently store the date. However, I would like to know how whether the jsFiddle is the appropriate way to use the Bootstrap datepicker widget with knockout.js i.e.

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

      ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).datepicker("destroy");
        });
    },
    update: function(element, valueAccessor) {
    }
};

Solution

  • Here is a sample of how you could accomplish this with the datepicker that you are using:

    ko.bindingHandlers.datepicker = {
        init: function(element, valueAccessor, allBindingsAccessor) {
          //initialize datepicker with some optional options
          var options = allBindingsAccessor().datepickerOptions || {};
          $(element).datepicker(options);
    
          //when a user changes the date, update the view model
          ko.utils.registerEventHandler(element, "changeDate", function(event) {
                 var value = valueAccessor();
                 if (ko.isObservable(value)) {
                     value(event.date);
                 }                
          });
        },
        update: function(element, valueAccessor)   {
            var widget = $(element).data("datepicker");
             //when the view model is updated, update the widget
            if (widget) {
                widget.date = ko.utils.unwrapObservable(valueAccessor());
                if (widget.date) {
                    widget.setValue();            
                }
            }
        }
    };
    

    It did not look like there was any destroy functionality, so I removed that piece. This handles the widgets changeDate event to update the view model, when a user changes the date. The update function handles when the view model is changed to update the widget.

    If you want to bind the value to a non-observable, then it would take a little more code. Let me know if that is something that you need to support.

    http://jsfiddle.net/rniemeyer/KLpq7/