Bootstrap 3 radio buttons are easy to set up to get a nice looking UI that works great on touch-based devices:

But if you bind those pretty radio buttons to a Knockout 3 view model using the Knockout checked binding, your view model doesn’t get updated.  The UI still updates just fine to show which radio button was selected, but the Knockout value doesn’t change when the radio button selection changes.

It would be nice if it was this simple and it just worked, but it doesn’t.  I also tried using the new Knockout checkedValue binding, which lets you set the value the view model (in this case, selectedOption) gets when the radio button is checked.  But that didn’t help, either.  Apparently, the Bootstrap JS is colliding with the click or change event Knockout is listening on to update its view model.

So how do we get the nice, touch-friendly Bootstrap radio buttons to work with Knockout bindings?  After some trial and error, the answer was pretty simple.

First, I took out the Bootstrap JS radio button signature, data-toggle=”buttons” from the outer div that has the “btn-group” CSS class.  That adds back in the previously hidden input radio button UI (the circles), but it removes the colliding Bootstrap JS call, so Knockout biding can work.

Next, I added the “active” CSS class to the labels in the “btn-group”.  Since we took out the Bootstrap JS help, we’re on our own for adding the “active” class back in.  I used the Knockout css binding on the labels to do this.

data-bind="css: { 'active': selectedOption() === 'Option 1' }"

Note the use of parentheses with selectedOption.  Since the Knockout view model properties are functions, you have to use parentheses to evaluate the function and get the value.

If you like this look, you could stop here.  Knockout is happy, and the UI looks OK.

But if you don’t like the circles showing up on the radio button options, you can put in some CSS to fix it:

label.btn > input[type='radio']
    display: none;

And now we get the look we want with the functionality we want: