bootstrap, knockout.js, radio buttons group, can play nice and can be dynamic

I’ve tried to use knockout.js (KO) with bootstrap and I found that it will not work out of the box. The main reason – bootstrap will prevent the click events to go to knockoutjs.

I had two challenges:
1. How to notify KO about the click event without breaking bootstrap?
2. How to do KO data binding with the radio buttons?

After some investigation/googling the answer for challenge 1 became apparent – use custom bindings in knockoutjs: http://knockoutjs.com/documentation/custom-bindings.html

That solved the click event on the buttons.

The answer for number 2: How to use knockoutjs to create dynamically the items (buttons) in my bootstrap radio button group? – It was harder for me – All examples were with static/predefined radio buttons.

The solution came again from the KO documentation – I just did a careful modification of their example for the checkbox to a radio button.
I have the working example below in a gist extracted from my jsfiddle

The key code:

<div class="btn-group" data-toggle="buttons" data-bind="foreach: items">
    <label class="btn btn-primary">
    <input type="radio" name="options" data-bind="checkedValue: $data.id, bsChecked: $root.chosenItem" />
    <span data-bind="text: itemName"></span>
    </label>
</div>​

..and the full gist:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>knockoutjs, bootstrap and dynamic radio buttons group – jsFiddle demo by ntodorov</title>
<script type='text/javascript' src='//code.jquery.com/jquery-2.1.3.js'></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type='text/javascript' src="http://knockoutjs.com/downloads/knockout-3.0.0.js"></script>
<script type='text/javascript' src="https://netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
ko.bindingHandlers.bsChecked = {
init: function (element, valueAccessor, allBindingsAccessor,
viewModel, bindingContext) {
var value = valueAccessor();
var newValueAccessor = function () {
return {
change: function () {
value(element.value);
}
}
};
ko.bindingHandlers.event.init(element, newValueAccessor,
allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor,
viewModel, bindingContext) {
if ($(element).val() == ko.unwrap(valueAccessor())) {
setTimeout(function () {
$(element).closest('.btn').button('toggle');
}, 1);
}
}
}
var viewModel = {
items: ko.observableArray([
{ id: 1, itemName: 'Choice 1' },
{ id: 2, itemName: 'Choice 2' },
{ id: 3, itemName: 'Choice 3' },
{ id: 4, itemName: 'Choice 4' }
]),
chosenItem: ko.observable(2)
};
ko.applyBindings(viewModel);
});//]]>
</script>
</head>
<body>
<div class="btn-group" data-toggle="buttons" data-bind="foreach: items">
<label class="btn btn-primary">
<input type="radio" name="options" data-bind="checkedValue: $data.id, bsChecked: $root.chosenItem" />
<span data-bind="text: itemName"></span>
</label>
</div>
<pre data-bind="text: JSON.stringify(ko.toJS($root), null, 2)"></pre>
</body>
</html>

 

If you have any questions, feel free to use the comments section bellow.

Happy coding and let’s code the planet togeter! 🙂

bootstrap, knockout.js, radio buttons group, can play nice and can be dynamic

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s