Friday, January 31, 2014

Knockout Durandal DatePicker

While building your SPA application in Durandal or Knockout you may need your users to enter dates, such of Date Of Birth. Would it be nice to provide a DatePicker control for the user to pick the date. In this blog I will show you how to include a DatePicker in your durandal app and do knockout binding.

First of all identify what DatePicker JQuery control you want to use in your SPA application. I typically use Zurb Foundation in my applications, hence I decided to use foundation’s DatePicker, which is based on Bootstrap’s DatePicker. Instead of this you can use Bootstrap’s DatePicker, JQueryUI’s DatePicker or any other DatePicker.

Once you finalized the DatePicker, include that javascript file into the code by any mechanism, such as script tags, bundleconfig in MVC, require AMD etc. For simplicity I am using script tags

    <script src="/Scripts/foundation/foundation-datepicker.js"></script>

Also include the corresponding styles
    <link href="/content/foundation-datepicker.css" rel=="stylesheet"></script>

In addition to the datepicker javascript, I also use moment javascript for formatting dates. So let’s include that script file as well

<script src="/scripts/moment-with-langs.js"></script>

After doing this minimal work, let’s move to Knockout where we have to tell knockout to attach our DatePicker controller. This is done by defining our own binding attribute. Similar to the built-in binding let’s define a custom binding called datepicker. In this custom binding we will do the following steps
  • Attach the DatePicker control to the textbox element on the init method
  • Define format of the date (if needed)
  • Register the change event and in that change event update the model value
  • Whenever the model is updated, change the value of the DatePicker control
  • Format the date using moment (if needed)

Here is the code that does the all the above steps

    ko.bindingHandlers.datepicker = {
        init: function (element, valueAccessor) {
            $(element).fdatepicker({ format: 'mm/dd/yyyy' });
            var value = valueAccessor();

            ko.utils.registerEventHandler(element, "change", function () {
                value(element.value);
            });
        },

        update: function (element, valueAccessor, allBindingsAccessor, viewModel)
        {
            var value = valueAccessor();
            var mmt = moment(value());
            if (mmt.isValid() === false) {
                value("");
                element.value = "";
            }
            else {
                element.value = mmt.format('L');
            }
        }
    };

As I am doing this in my Durandal SPA, I can use composition to define the knockout binding handler as shown below

    composition.addBindingHandler('datepicker', {
        //init & update code as above
    });

The above configuration is a onetime process. After setting up the datepicker binding attribute we can use it anyplace in our application by using the datepicker databinding attribute as shown below

         <input type="text" placeholder="" data-bind="datepicker: DateOfBirth" />

Here is the output of our knockout DatePicker control


1 comment:

  1. Nice post,
    Thanks and keep up the good work

    ReplyDelete