Knockout out provides a sophisticated way to use jQuery methods with your binding. You can use a custom binding feature provided by knockout for this purpose. Suppose I want to use SlideDown
and slideUp
methods of jQuery to show and hide the elements. Although it can be achieve by using the “visible” property of knockout, but I want to do it in a fancy way.
Add a sub property in ko.bindingHandlers
and write your custom code in init and update method. This blog does not explain how to create custom binding. You can find its help in the knockout documentation. Here is the complete code of the custom binding for show/hide element using jQuery.
ko.bindingHandlers.collapseVisible = {
init: function (element, valueAccessor) {
var value = valueAccessor();
$(element).toggle(ko.utils.unwrapObservable(value));
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor();
var allBindings = allBindingsAccessor();
var duration = allBindings.slideDuration || 500;
ko.utils.unwrapObservable(value) ? $(element).slideDown(duration) : $(element).slideUp(duration);
}
};
In the init method set the initial state of the element. This method calls once for each DOM element. Get element using $(element)
and perform action which you want.
Whenever the associated observable change, the ko calls you update callback method. In this example I get the value of element using ko.utils.unwrapObservable(value)
and call slideUp
or slideDown
method according to value.
Now next step is to bind your DOM element using ‘CollapseVisible’ custom binding.
<div data-bind="collapseVisible: displayDetail, slideDuration: 1000" class="desc">
Lorem Ipsum is simply dummy text of the ...
</div>
So whenever the value of displayDetail
observable will change. The Update callback method will be called and according to value the slideUp
and slideDown
methods will be called.
Complete Solution
Now here is complete working solution for it. Set style for your element.
<script src="Scripts/jquery-2.0.0.js"></script>
<script src="Scripts/knockout-2.2.1.js"></script>
<style>
.box
{
border: 1px black solid; width: 650px; margin-left: auto; margin-right: auto;
}
.box .title
{
padding: 8px; background-color: #e1e1e1; border-bottom: 1px black solid;
}
.box .title .showButton
{
float: right;
}
.box .desc
{
padding: 8px;font-size:12px;
}
</style>
Set your element, assign CSS classes and set binding etc.
<div class="box">
<div class="title">
<span data-bind="html: title"></span>
<a class="showButton" href="#"
data-bind="html: showButtonText, event: { click: onShow }"></a>
</div>
<div data-bind="collapseVisible: displayDetail, slideDuration: 1000" class="desc">
Lorem Ipsum is simply dummy...
</div>
</div>
Finally create your view model, custom binding and bind them to your page.
<script type="text/javascript">
var vm = {
title: "Collapsible Box",
showButtonText: ko.observable('Show'),
displayDetail: ko.observable(false),
onShow: function () {
var newVal = !this.displayDetail();
this.displayDetail(newVal);
this.showButtonText(newVal ? "Hide" : "Show");
}
};
ko.bindingHandlers.collapseVisible = {
init: function (element, valueAccessor) {
var value = valueAccessor();
$(element).toggle(ko.utils.unwrapObservable(value));
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor();
var allBindings = allBindingsAccessor();
var duration = allBindings.slideDuration || 500;
ko.utils.unwrapObservable(value) ?
$(element).slideDown(duration) : $(element).slideUp(duration);
}
};
ko.applyBindings(vm);
</script>