Clint
Clint

Reputation: 1159

KnockoutJS radio button checked binding that works with JQuery Mobile 1.4?

I've been trying to work out how to get a checked binding to work with Knockout and JQuery Mobile. For some reason the vanilla Knockout JS "checked" binding does not work:

<fieldset data-role="controlgroup">
    <legend>Your favorite flavor:legend>
    <input type="radio" name="flavor-selection" value="Chocolate" id="flavor-selection-chocolate" data-bind="checked: flavor" />
    <label for="flavor-selection-chocolate">Normal</label>
    <input type="radio" name="flavor-selection" value="Vanilla" id="flavor-selection-vanilla" data-bind="checked: flavor" />
    <label for="flavor-selection-vanilla">Party</label>
</fieldset>

Any ideas why?

Upvotes: 0

Views: 366

Answers (1)

Clint
Clint

Reputation: 1159

It turns out that jQuery Mobile styles the label for the radio button in order to display the radio selection (hiding the actual radio button itself).

I tried the suggestion found here: http://codeclimber.net.nz/archive/2013/08/16/How-to-bind-a-jquery-mobile-radio-button-list-to.aspx but didn't have any success with it - I suspect it might have only worked with a previous version of jQuery Mobile.

Here's my alternative:

Create a custom binding to switch the "ui-radio-on" and "ui-radio-off" classes on the label depending on the checked state of the hidden checkbox:

ko.bindingHandlers.jqMobileRadioChecked = {
    init: function (element, valueAccessor, allBindingsAccessor, data, context) {
        ko.bindingHandlers.checked.init(element, valueAccessor, allBindingsAccessor, data, context);
    },
    update: function (element, valueAccessor, allBindingsAccessor, data, context) {

        var viewModelValue = valueAccessor();
        var viewModelValueUnwrapped = ko.unwrap(viewModelValue);

        var $el = $(element);
        var $label = $el.siblings("label[for='" + $el.attr("id") + "']");
        if (viewModelValueUnwrapped === $el.val()) {
            $label.removeClass("ui-radio-off");
            $label.addClass("ui-radio-on");
        } else {
            $label.removeClass("ui-radio-on");
            $label.addClass("ui-radio-off");
        }
    }
};

Then the HTML simply becomes:

<fieldset data-role="controlgroup">
    <legend>Your favorite flavor:legend>
    <input type="radio" name="flavor-selection" value="Chocolate" id="flavor-selection-chocolate" data-bind="jqMobileRadioChecked: flavor" />
    <label for="flavor-selection-chocolate">Normal</label>
    <input type="radio" name="flavor-selection" value="Vanilla" id="flavor-selection-vanilla" data-bind="jqMobileRadioChecked: flavor" />
    <label for="flavor-selection-vanilla">Party</label>
</fieldset>

Upvotes: 1

Related Questions