Bootstrap datepicker with knockout.js databind

前端 未结 4 1763
耶瑟儿~
耶瑟儿~ 2020-12-04 22:25

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.

相关标签:
4条回答
  • 2020-12-04 22:46

    Here is what I Ended up

    ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        //initialize datepicker with some optional options
    
        var options = {
            autoclose: true,
            format: 'yyyy-mm-dd',
        }
    
        //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)) {
                var myDate = event.date;
                var month = myDate.getMonth() + 1;
                var monthText = month;
    
                if (month < 10)
                    monthText = "0" + month;
    
                var day1 = parseInt(myDate.getDate());
                var dayText = day1;
    
                if (day1 < 10)
                    dayText = '0' + day1;
    
                value(myDate.getFullYear() + '-' + monthText + '-' + dayText);
            }
        });
    },
    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());
            widget.setValue(widget.date);
        }
    }};
    
    0 讨论(0)
  • 2020-12-04 22:48

    The accepted answer didn't work for me with the current version of the date picker. The input wasn't being initialized with the value of the observable. I made an updated binding, to which I added this:

    $(element).datepicker('update', dataSource());
    

    That seems to do the trick.

    Here's an updated fiddle that uses the latest available date picker, Bootstrap, jQuery, and Knockout: http://jsfiddle.net/krainey/nxhqerxg/

    Update:

    I experienced some difficulty with the date picker not playing nicely with the observable when a user would edit the value in the text field manually. The tool would immediately parse the date, and plug the result into the input field.

    If the user tried to edit 10/07/2014, for example, and used the backspace or delete to remove a number (10/0/2014), the resulting value would be parsed immediately and inserted into the text input. If the value was, for a moment, 10/0/2014, the picker would shift the calendar to 09/30/2014, and plug that value into the text field. If I tried to edit the month, and the value was, for a moment, 1/7/2014, the picker would shift to January 7, 2014, and plug that value in to the text field.

    You can see that behavior in this fiddle:

    http://jsfiddle.net/krainey/nxhqerxg/10/

    I had to update my binding with a special handler to detect focus, and bind a one-time blur event to get it to handle manual edits correctly.

    $(element).on("changeDate", function (ev) {
        var observable = valueAccessor();
        if ($(element).is(':focus')) {
            // Don't update while the user is in the field...
            // Instead, handle focus loss
            $(element).one('blur', function(ev){
                var dateVal = $(element).datepicker("getDate");
                observable(dateVal);
            });
        }
        else {
            observable(ev.date);
        }
    });
    

    The fiddle referenced in the original answer has been updated to reflect this:

    http://jsfiddle.net/krainey/nxhqerxg/

    0 讨论(0)
  • 2020-12-04 22:58

    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/

    0 讨论(0)
  • 2020-12-04 22:58

    my current version is a mix between the already shown solutions:

    ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
    
        var unwrap = ko.utils.unwrapObservable;
        var dataSource = valueAccessor();
        var binding = allBindingsAccessor();
    
        //initialize datepicker with some optional options
        var options = allBindingsAccessor().datepickerOptions || {};
        $(element).datepicker(options);
        $(element).datepicker('update', dataSource());
        //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");
    
        var value = ko.utils.unwrapObservable(valueAccessor());
    
        //when the view model is updated, update the widget
        if (widget) {
            widget.date = value;
            if (widget.date) {
                widget.setValue();
                $(element).datepicker('update', value)
            }
        }
    }};
    
    0 讨论(0)
提交回复
热议问题