Knockout Bootstrap datepicker binding

An example of a knockout.js custom binding for the bootstrap date-picker plugin

by krainey

HTML

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/css/datepicker.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/js/bootstrap-datepicker.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="datePicker: myDate" >
<div>
    The current value is: <span data-bind="text: myDate" />    
</div>

JavaScript

ko.bindingHandlers.datePicker = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var unwrap = ko.utils.unwrapObservable;
            var dataSource = valueAccessor();
            var binding = allBindingsAccessor();
            var options = {
                keyboardNavigation: true,
                todayHighlight: true,
                autoclose: true,
                daysOfWeekDisabled: [0, 6],
                format: 'mm/dd/yyyy'
            };
            if (binding.datePickerOptions) {
                options = $.extend(options, binding.datePickerOptions);
            }
            $(element).datepicker(options);
            $(element).datepicker('update', dataSource());
            $(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);
                }
            });
            //handle removing an element from the dom
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                $(element).datepicker('remove');
            });
        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            $(element).datepicker('update', value);
        }
    };

var vm = function ()
{
    var myDate=ko.observable(new Date());
    return {
        myDate: myDate,
    }
}();

ko.applyBindings(vm);