My last article explained the
Binding Context in KnockoutJS. This article explains how to create custom
binding in KnockoutJS. Knockout provides the option to create and use our own
bindings.
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: <inputdata-bind="value: logEntry, valueUpdate: 'keyup'"/> </p>
<divdata-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.
That's how to create our own custom bindings whenever we need.
The complete example for this custom binding handler is given below with source.
Happy Coding :)