Friday, October 4, 2013

How to Create Custom Binding in KnocoutJS


Why Custom Binding?

This question might be raised when you read the title of this article. Well, you need to go for custom binding when you want more control and flexibility over elements and observables used. If you want to create your own interactive controls then the right way is to go for custom binding. Here is the goodexample for custom binding provided by KnockoutJS.

All the bindings available in the KnockoutJS are the sub properties of a "ko.bindingHandlers" object.
 
Creating Custom Binding

In order to create the custom binding, we need to add a property with your custom binding name and assign an object with two callback functions.
 
ko.bindingHandlers.myCustomBindingName = {
        init:
function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        },

        update:
function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        }

    }
 

Here you can see that we have added a property myCustomBindingName assigned with an object that has init and update callbacks. Let us see the callbacks in detail.
 
The init callback

The init callback function will be executed when the binding is applied the very first time. In this callback, we can have the initial setup necessary for the custom binding such as attaching events, setting up the initial state for variables and so on.

Note: the init callback function will be called only one when the binding is applied.

The update callback

The update callback function will be called whenever the associated observable is changed. While binding your custom binding handler with the element, if you have associated/assigned an observable to your custom binding handler then the update callback will be executed whenever you change the associated/assigned observable.

For example, you have a custom binding handler, say "animateItem" that does some animation whenever an item is added to the collection. The animateItem binding handler accepts an observable that decides whether the added item should be animated on the screen or not based on the observable true/false value.
 
Whenever you update the observable, the update callback of your binding callback will be called with the updated value.
 
The parameters of callback functions
 
These init and update callback functions have the same set of parameters. They are element, valueAccessor, allBindingsAccessor, viewModel and bindingContext. Let us discuss these one by one.
 
element The DOM element on which our custom binding is applied.
valueAccessor The JavaScript function that will return the value assigned/associated with the binding.
You can use the "ko.unwrap" utility function to get the value assigned
allBindingAccessor The JavaScript function that will return all the values assigned/associated with
all the bindings bound with the current DOM. Suppose you have some other KO bindings say
value, visible
then the allBindingAccessor will give you those values and visible binding values also.
viewModel The viewmodel object that is bound to the entire page using "ko.applyBindings()". But when your
binding is within the with binding or foreach binding then the viewModel parameter will have
the $data context instead of the main viewModel.
bindingContext The binding context available for the DOM element. This parameter will have all other bindings
($parent, $parents and $root...)
as a special property.

Example
 
We will discuss the custom binding with an example. We will create a custom binding where we can display the change log for an input box.
 
<p>Change this value: <input data-bind="value: logEntry, valueUpdate: 'keyup'" /> </p>
<div data-bind="yourBindingName: logEntry">
    <ul>
    </ul>
</
div>

In this example view, we have an input element bound to the logEntry observable assigned/associated with the value binding. And we have a div to which we have bound our custom binding "yourCoustomBinding". Since we have associated the logEntry observable with our custom bidning, the update callback function will be executed whenever the text in the input box is changed.
ko.bindingHandlers.yourBindingName = {
        init:
function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
// Setup the events, variables..
$(element).css(
"background-color", "rgb(228, 222, 222)");
         },
        update:
function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
           
var text = ko.unwrap(valueAccessor()); // Getting the update log text
            $(
'ul').append('<il> The new text is : ' + text + '</il>');// Adding into the ul as il.
        }
    }
     
var viewModel = { logChange: ko.observable("Type some thing") };
     ko.applyBindings(viewModel);

 
In the init callback function, as an initial setup, we are setting the background color for the change log container. When you start changing the text, the update callback will be called. In the update callback, we are unwrapping the valueAccessor to get the value passed to our custom binding. Then we are appending the changed text to the ul element as an il item.

No comments:

Post a Comment