Mobile Zone is brought to you in partnership with:

Simone Chiaretta is a Software Architect and Developer from Milano, Italy that enjoys sharing via his blog his development experiences and more than decennial knowledge on web development with ASP.NET and other web technologies. He is Microsoft MVP in ASP.NET and he has been involved in many Open Source projects, but now he focuses only on SubText and taking it to the next level. He just wrote a book: Beginning ASP.NET MVC, published by Wrox Simone is a DZone MVB and is not an employee of DZone and has posted 67 posts at DZone. You can read more from them at their website. View Full User Profile

How to Build a jQuery Mobile Radio Button List to a Knockout.js Variable

08.29.2013
| 3133 views |
  • submit to reddit

Rendering a radio button list with jQuery Mobile is pretty easy: you just write a normal radio buttons list, apply the jQuery Mobile data attribute and you a get nice mobile “touch” friendly radio button list.

radiobutton-group

Having it also send back to a Knockout.js variable the value of the selection is easy too: just apply the checked binding to the radio button.

Standard Radio Button List with jQuery Mobile and Knockout.js

This is the code that turns a normal radio button list to the jQuery Mobile horizontal group with binding to a Knockout.js variable.

<fieldset data-role="controlgroup" data-type="horizontal">
  <label>
    <input type="radio" value="Yes" name='Vote'
      data-bind="checked: Vote" />Yes</label>
  <label>
    <input type="radio" value="No" name='Vote'
      data-bind="checked: Vote" />No</label>
  <label>
    <input type="radio" value="Abstain" name='Vote'
      data-bind="checked: Vote" />Abstain</label>
</fieldset>


<script type="text/javascript">
    viewModel = {
        Vote: ko.observable('Yes')
    };

    ko.applyBindings(viewModel);
</script>

You can see a radio button list at work on this jsFiddle: http://jsfiddle.net/simonech/pyjV3/

Unfortunately, this code only works in one direction: from the HTML control to the variable. It doesn’t work the other way around. I’ve explained the reason why in my previous blog post about how to two-way bind a jQuery mobile flip switch to a Knockout.js variable. The solution to the problem is also the same as with the flip switch: a custom binding is needed in order to let Knockout.js know how to update the UI of the radio button list when the bound variable changes value.

Custom Binding for Radio Button

In reality, the custom binding is not applied to the radio buttons but to the control group that contains them. Let’s first see the code and then I’ll explain what it does. You can see it working on http://jsfiddle.net/simonech/cQaDm/1/.

ko.bindingHandlers.jqCheckboxRadio = {
    init: function(element, valueAccessor) {
        var currentValue = valueAccessor();
        $(element).controlgroup(currentValue);
        $(element).attr("data-role", "controlgroup");
        $( "input[type='radio']",element).on( "checkboxradiocreate",
            function( event, ui ) {$(element).data( "init", true )} );
    },
    update: function(element, allBindingsAccessor) {
        var currValue = allBindingsAccessor().value();
        var initialized = $(element).data( "init");
        if(initialized){
            $("input[type='radio']",element).prop( "checked", false )
                .checkboxradio( "refresh" );
            $("input[type='radio'][value='"+currValue+"']",element)
                .prop( "checked", true ).checkboxradio( "refresh" );
        }
    }
};

Compared to the one for the flip switch, this binding is a bit easier, but has to work around a bug in the jQuery Mobile API for the controlgroup widget.

The init Method

The init method creates the control group via API by calling the .controlgroup method, with the options specified in the binding (for example, to make it horizontal, or mini). The next line, which applies the data-role attribute again is to work around a bug that wouldn’t render rounded corners.

The last line of the init method is needed to keep track of when all radio buttons inside the control group are initialized, otherwise the update method will fail if it’s called before they have been initialized: this is done by registering a callback on the checkboxradiocreate event of the checkboxradio jQuery Mobile widget.

The Update Method

This method is a bit more straightforward: it just verifies that the radio buttons are initialized, resets all their checked properties to false (to account for when the value of the variable is undefined) and then “checks” the radio button whose value matches the value of the bound variable.

Applying the Binding to the HTML Radio Buttons

The last step is to apply the binding to the HTML code.

<fieldset data-bind="value: Vote, jqCheckboxRadio: { mini: 'true', type: 'horizontal' }">
    <label><input type="radio" value="Yes" name='VoteGroup'
        data-bind="checked: Vote" />Yes</label>
    <label><input type="radio" value="No" name='VoteGroup'
        data-bind="checked: Vote" />No</label>
    <label><input type="radio" value="Abstain" name='VoteGroup'
        data-bind="checked: Vote" />Abstain</label>
</fieldset>

Complete Demo

You can view the complete demo, where you can see how one version of the control only works in one direction, while the one with the custom binding works also in the other, on the jsFiddle: http://jsfiddle.net/simonech/cQaDm/2/



Published at DZone with permission of Simone Chiaretta, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)