Knockout + Bootstrap 3 Radio Buttons

The bootstrap buttons and the knockout checked binding are still not playing nice:

  • knockout uses the click event inside the checked binding to tigger the underlaying observable to change
  • bootstrap subscribes on the click event to do the toggling but calls e.preventDefault() so KO won’t be notified about the click.

One possible solution is to create a custom binding handler where you subscribe on the change event (this is fired by bootstrap on toogle) and set your observables value there:

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); 
        }
    }
}

And use it in your view with:

<label class="btn btn-primary">
    <input type="radio" name="options" id="option1" value="1" 
           data-bind="bsChecked: optionsValue"> Option 1
</label>

Original demo using Bootstrap 3.0.2 JSFiddle.
Updated demo using Bootstrap 3.2.0 JSFiddle.

Leave a Comment