Wednesday, April 9, 2014

Bundle Knockout Data-Bind

In one my projects I ran into a scenario where I need to specify multiple bindings for a textbox. Here is the code I used to this multiple bindings

<input type="text" data-bind="value: model.Allergies.Value,
css: {focusctrl: model.Allergies.ColourType() === 1,
correctctrl: model.Allergies.ColourType() === 2},
event: { focus: function() {$root.resetColour(model.Allergies)} }" />

The problem here is have several of these text boxes (about 50, I guess not a good design, but is what the user wants). I don’t want to repeat this binding several times (DRY). I want to bundle these bindings (like a function) so that I can avoid duplication and keep the code clean.

Luckily Knockout provides the functionality I am looking. It provides “ko.applyBindingsToNode” to dynamically do the databinding. So I defined a custom binding in which I am in turning doing the databinding I want. Here is my custom binding

ko.bindingHandlers.notesvalue = {
    init: function (element, valueAccessor, allBindingsAccessor, data) {
        var field = valueAccessor();
        field.focusctrl = ko.computed(function () { return field.ColourType() === 1 });
        field.correctctrl = ko.computed(function () { return field.ColourType() === 2 });
        ko.applyBindingsToNode(element, {
            value: field.Value,
            css: { focusctrl: field.focusctrl, correctctrl: field.correctctrl },
            event: {
                focus: function() {
                    if(field.ColourType() === 1){

In the above code, I am just using the initializer and doing the bundling of the value, css and event data-binding. As you see, in the above code I am also defining computed attributes. That’s neat.

With my bundling code my databinding is reduced to as below

<input type="text" data-bind="notesvalue: model.Allergies" />

This is something I can live with. J.