Having trouble viewing Cygnet-Infotech Site® ? It's because the browser you are using is not supported. Please upgrade to one of the latest versions.

    Introduction to Knockout Custom Binding Handlers

    Share 0 Comment - Application Management

    Introduction-to-Knockout-Custom-Binding-Handlers

    Knockout JS (commonly known as KO) is a great JavaScript Library that works on top of your web application on any mainstream browser. It helps creating rich, responsive and interactive UIs using MVVM (Model-View-View-Model) pattern with a clean underlying data-model. It is compact and is suitable for any Server or Client-side technology.
    Knockout JS is known for its dynamic architecture that enables a UI to update on itself automatically. It comes with lots of bindings that enable ‘Declarative Binding’ using ‘Observable ViewModel’ on the client (browser) that helps implement changes automatically when the data source of any UI changes as a result of user intervention. Hence, for any UI changes or manipulations in the DOM elements, Knockout JS has inbuilt bindings that handle the inconsistencies without complexities and chaos.
    Some of the readily available bindings of KO are ‘foreach,’ ‘text’, ‘html’, ‘visible’ etc. However, sometimes readily available bindings are not enough to use them as it is. Especially, when you have got third-party JavaScript library which you need to integrate and for which you need to write UI update code.
    Hmm! That’s where you require to create your own bindings, i.e. Custom Bindings.

    Custom Bindings Handlers in Knockout JS

    KO provides this sophisticated way to gracefully handle complex behaviors of third-party widgets/components.
    Here’s how

    ko.bindingHandlers.myBinding = {
    init: function(element, valueAccessor, allBindings, data, bindingContext) {
    // this will be called first time only when the binding is evaluated for the element
    },
    update: function(element, valueAccessor, allBindings, data, bindingContext) {
    // this will be called once when the binding is first time applied to the element and then again when associated observables are modified
    }
    };

    • element – DOM element. The element on which the binding is applied.
    • valueAccessor – returns the bound value of the element. Sometimes it may be a value and sometimes an observable.
    • allBindings – an object that provides access to all the model values bound to the element.
    • data – return view model
    • bindingContext – This is an object that holds the binding context of the element as $parent, $data etc.

    A detailed description for Custom Bindings can be viewed at Custom bindings with Knockout
    In this tutorial, I am going to present a couple of simple binding handlers that can make HTML elements binding pretty easy to deal with!

    A) Common HTML Element Bindings

    1) Image: src attribute

    It is pretty common to bind <img/> tags, but becomes annoying to use attr binding handler. This is the shortcut to get a cleaner syntax.

    It will look like:


    ko.bindingHandlers.src = {
    update: function (element, valueAccessor) {
    ko.bindingHandlers.attr.update(element, function () {
    return {
    src: valueAccessor()
    };
    });
    }
    };

    It is declared as:


    < img data-bind="src: $data.myImage" / >

    Instead of:

    < img data-bind=”attr: {src: $data.myImage }” / >

    Sample here: http://jsfiddle.net/CygnetInfotech/vybnerbo/

    2) Styling: margin, alignment

    Styling is a major aspect in the HTML world and providing inline styles is a common practice (though not recommended!). What if it becomes easier to bind inline styles with a simple syntax?

    Here it goes:


    ko.bindingHandlers.setStyle = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    ko.bindingHandlers.style.update(element, function () {
    return {
    margin: ko.unwrap(valueAccessor()),
    textAlign: allBindingsAccessor().textAlign
    };
    }, allBindingsAccessor, viewModel, bindingContext);
    }
    };

    It is declared as:

    <div id="content" data-bind="setStyle: $data.margin, textAlign: $data.alignment">
    </div>

    Instead of:

    <div id=”content” data-bind=”style: {margin: 10px, textAlign: center}”>
    </div>

    Sample here: http://jsfiddle.net/CygnetInfotech/fo1o1bkm/

    3) Toggle

    This tiny piece of code can really help reduce some clutter in viewmodels. Often times, it is required to bind a click handler only for setting the visibility (show/hide) of HTML elements.

    ko.bindingHandlers.toggle = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    //unwrap value
    var value = valueAccessor();
    ko.applyBindingsToNode(element, {
    click: function () {
    value(!value());
    }
    });
    }
    };

    It can be declared as:

    <button data-bind="toggle: isHidden">Show/Hide</button>

    Instead of:


    <button data-bind="click: function(){isHidden(!isHidden());}">Show/Hide</button>

    Sample here: http://jsfiddle.net/CygnetInfotech/yfr80f91/

    B) Knockout Utility Function Binding

    1) toJSON

    Knockout has a number of utility functions used by the library itself. One such example is ko.toJSON. It can be used to quickly bind entire view model (having both observable and non-observable properties) that can be passed to an Ajax call directly and quickly see all changes going on.

    ko.bindingHandlers.toJSON = {
    update: function (element, valueAccessor) {
    return ko.bindingHandlers.text.update(element, function () {
    return ko.toJSON(valueAccessor(), null, 2);
    });
    }
    };

    It can be declared as:

    < pre data-bind="toJSON: $data" > < /pre >

    Instead of:

    < pre data-bind="text: ko.toJSON($data)" > < / pre >

    Sample here: http://jsfiddle.net/CygnetInfotech/r1sL2ngc/

    C) Third Party Controls: jQuery UI controls bindings

    1) Date Picker
    Binding to a third-party control for example, jQuery UI datepicker control! This could be all the way easy to allow the control to deal with Date object instead of working with strings.

    ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
    //initialize date picker
    var options = allBindingsAccessor().datepickerOptions || {};
    $(element).datepicker(options);
    //handle change
    ko.utils.registerEventHandler(element, "change", function () {
    var observable = valueAccessor();
    observable($(element).datepicker("getDate"));
    });
    //handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
    $(element).datepicker("destroy");
    });
    },
    update: function (element, valueAccessor) {
    var value = ko.unwrap(valueAccessor()),
    current = $(element).datepicker("getDate");

    if (value - current !== 0) {
    $(element).datepicker("setDate", value);
    }
    }
    };

    It can be declared as:

    < input data-bind="datepicker: currentDate, datepickerOptions: { minDate: new Date(), dateFormat: 'mm/dd/yy' }" / >

    Sample here: http://jsfiddle.net/CygnetInfotech/qsqc11fu/

    2) jQuery dialog
    One of the most widely used features in a JS-based web application is dialog. Often we encounter issues. For example, on closing a dialog, the KO bindings are not released properly, which leads to random UI behavior in which it doesn’t show the refreshed content, even when the dialog is opened and closed multiple times and at last leads to a hair scratching situation!

    Aghast..!!! But wait, what if we leave all the dialog bindings to knockout itself only?

    Here it shows how:

    ko.bindingHandlers.jqDialog = {
    init: function (element, valueAccessor) {
    var options = ko.unwrap(valueAccessor()) || {}; //handle disposal
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
    $(element).dialog("destroy");
    });

    $('.ui-dialog-content[id]').each(function () {
    if (element.id == this.id) {
    $(this).dialog("destroy").remove();
    }
    });
    $(element).dialog(options);
    }
    };

    It can be declared as:

    < div id="HelloDialogId" title="Hello Dialog" data-bind="jqDialog: {height: 100, width: 200, modal: true, draggable: true, resizable: false, autoOpen: false,
    close: function () { isOpen(false) }},
    openDialog: isOpen" >
    < p > Hello! < / p >
    < / div >

    Description:

    jqDialog: It is the custom binding handler that allows to define jQuery dialog’s syntax in a simple and easy manner.

    openDialog: It is the custom binding handler that handler open/close of the dialog on the basis of isOpen flag. When the value for isOpen is set to true, the dialog is opened and when set to false the dialog is closed.

    The fiddle in the example also covers another binding handler for jQuery buttons. It is defined as:

    ko.bindingHandlers.jqButton = {
    init: function (element, valueAccessor) {
    var options = ko.utils.unwrapObservable(valueAccessor()) || {};
    //handle disposal
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
    $(element).button("destroy");
    });
    $(element).button(options);
    }
    };

    It is declared as:

    < button data-bind="click: clickMe, jqButton: { icons: { primary: 'ui-icon-tag' } }" > Click Me! < / button >

    Sample here: http://jsfiddle.net/CygnetInfotech/Lnr12bk6/

    3) Loader

    Any operation which is long running or requires server interaction needs a loading mask to be applied to UI in order to restrict users from making subsequent calls. The same can be handled through custom binding, making it more maintainable code (as it can be required in multiple pages depending upon the UI implementation)

    ko.bindingHandlers.loader = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    var value = valueAccessor(),
    //$element = $(element),
    valueUnwrapped = ko.utils.unwrapObservable(value),
    loadingMsg = allBindingsAccessor().loaderMsg,
    loadingElementId = allBindingsAccessor().loaderElement,
    $element = $('#' + loadingElementId);
    if (valueUnwrapped) {
    //load Mask
    $element.mask(loadingMsg);
    } else {
    //hide mask
    $element.unmask();
    }
    }
    };

    It can be declared as:

    < div id="loadMaksContents" >
    < div data-bind="loader: isBusy, loaderMsg: loaderMsg, loaderElement: 'loadMaksContents' >
    < / div >
    < / div >

    Description:

    loader: This is the custom binding handler that works on ‘isBusy’ boolean flag that controls the loading and unloading of the mask based on the flag value
    loaderMsg: this is the binding attribute that specifies the message to be displayed in load mask
    loaderElement: This is the binding attribute that specifies the id of the element upon which loading mask is to be applied

    Sample here: http://jsfiddle.net/CygnetInfotech/qzfz69ch/

    That’s all from my side. Hope you explore amazing possibilities in your development endeavors with these custom binding handlers ?

    Created and Compiled by:
    Surbhi Mahnot

Get in touch