Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Bootstrap datepicker and Knockout Model Binding

4.82/5 (5 votes)
30 May 2014CPOL1 min read 54.7K   1.2K  
Bootstrap datepicker and Knockout Model Binding

Introduction

Now a days, client side MVVM is a popular pattern using knockout.js. But the problem comes when we try to deal with date-time pickers and View Model binding. We can solve such problems using custom blinding handlers for knockout.

Background

I am working new with Knockout and MVVM. Everything was just fine except the date binding from a bootstrap date-time picker/ date time object send from server end. After Googling for sometime, I got a solution, which I am going to demonstrate here. Before we start, we need some .js libraries like:

  1. jquery
  2. bootstrap-datepicker
  3. knockout
  4. moment (really a good and simple js lib to deal with date time objects)

Using the Code

Let's start with the basic HTML to hold our date-time picker. Here two things are quite important:

  1. data-date-format: to point format of the date picker
  2. datepicker: which is a custom binding handler work for data binding, like value: in regular knockout
XML
<!--date inputed from client-->       
<div>
    <label class="control-label">Date From Client</label>
    <input type="text" readonly="readonly" 
    data-date-format="dd-mm-yyyy" class="datepicker" 
    data-bind="datepicker: dateFromClient" />
    <span class="help-block">Date with Formate of (dd-mm-yyyy)</span>
</div>
    
<!--date from server end-->       
<div>
    <label class="control-label">Date From server</label>
    <input type="text" readonly="readonly" 
    data-date-format="dd-mm-yyyy" class="datepicker" 
    data-bind="datepicker: dateFromServer" />
    <span class="help-block">ClientDate - 5 days, (dd-mm-yyyy)</span>
</div> 

The custom binding handler datepicker is declared like this. We can customize it even for the jquery date time picker if we want to.

JavaScript
/*Date picker value binder for knockout*/
ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().datepickerOptions || {};
        $(element).datepicker(options).on("changeDate", function (ev) {
            var observable = valueAccessor();
            observable(ev.date);
        });
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).datepicker("setValue", value);
    }
}; 

Now, we are going to use some utility functions to use moment.js to get current date time or to convert a server side datetime object to a given date format for client end.

JavaScript
/*Datetime issues with moment =>*/
function currentDate() {
    return moment();                             //sends current datetime
};

function clientDateStringFromDate(date) {
    return moment(date).format('DD-MM-YYYY');   //converts a date object to a given formate
}; 

Now, here is the View model for our view:

JavaScript
/*View model*/
function ViewModel() {
    var self = this;
    self.dateFromClient = ko.observable(currentDate());      //set current date to date picker
    self.dateFromServer = ko.observable(currentDate());      //set current date to date picker

    self.init = function() {
        self.getServerDate();
    };

    self.getServerDate = function () {
        var json = JSON.stringify({ date: self.dateFromClient()});     //serialize json to post 
        $.ajax({
            url: '../../Services/DateTestService.asmx/GetDate',
            dataType: "json",
            contentType: 'application/json; charset=utf-8',
            type:"POST",
            data:json,
            async: true,
            processData: false,
            cache: false,
            success: function (data) {
                //alert(data.d);                                //see what type of data we get   
                var date = clientDateStringFromDate(data.d);    //convert datetime object to date string.
                self.dateFromServer(date);
            },
            error: function (xhr) {
                alert('Error to connect to server.');
            }
        });
    };

    /*date inputed from client, change event*/
    self.dateFromClient.subscribe(function(newValue) {
        self.getServerDate();
    });
}  

Now let's finish with date picker wrapper and model binding.

JavaScript
$(document).ready(function () {   
    //apply the datepicker to field
    $('.datepicker').datepicker();

    //model binding
    var vm = new ViewModel();
    vm.init();                       //initialize the view model
    ko.applyBindings(vm);
}); 

I have demonstrated the basic date binding here. You can find more details in the project attachment, which is a Visual Studio 2010 solution.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)