Ron Harlev
Ron Harlev

Reputation: 16703

jquery mobile and knockout checkbox not updating with viewmodel

I have two jQuery Mobile checkboxes bound to the same knockout viewmodel member. I expect clicking on one check box to update the viewmodel and in turn update the other checkbox to be checked too. see example here

The HTML

<span data-bind="text: chk"></span>
<input id="checkbox1" name="" data-bind="checked: chk" type="checkbox">
<label for="checkbox1">A</label>
<input id="checkbox2" name="" data-bind="checked: chk" type="checkbox">
<label for="checkbox2">B</label>

The Javascript

function ViewModel(){
var self = this;

self.chk = ko.observable(false);
}

ko.applyBindings(new ViewModel());

I can see the model is updating, with a text field showing its value. But the checkbox is not

Upvotes: 1

Views: 1460

Answers (2)

srgstm
srgstm

Reputation: 3759

The problem is that jQuery Mobile has to refresh its custom drawing of a checkbox when underlying checkbox control changes its state but it cannot detect it when you change it programmatically via Knockout. It only detects onclick events. This has to be done via custom knockout bindings.

I have created a simple custom binding that works in all versions of KO (including the latest v3):

ko.bindingHandlers.jqmChecked = {
    init: ko.bindingHandlers.checked.init,
    update: function (element, valueAccessor) {
        //KO v3 and previous versions of KO handle this differently
        //KO v3 does not use 'update' for 'checked' binding
        if (ko.bindingHandlers.checked.update) 
            ko.bindingHandlers.checked.update.apply(this, arguments); //for KO < v3, delegate the call
        else 
            ko.utils.unwrapObservable(valueAccessor()); //for KO v3, force a subscription to get further updates

        if ($(element).data("mobile-checkboxradio")) //calling 'refresh' only if already enhanced by JQM
            $(element).checkboxradio('refresh');
    }
};

Should be used like this:

<input type="checkbox" data-bind="jqmChecked: someValue" id="checkbox1"/>

See a complete working example here:

http://jsfiddle.net/srgstm/ub6sq/

Upvotes: 5

Xiaodoudou
Xiaodoudou

Reputation: 326

Your issue is linked to Jquery mobile not knockout. The only solution I found to help you was to use a suscription on your model to work arround it.

function myViewModel(){
    var self = this;
    self.chk2      = ko.observable(false);
    self.chk       = ko.observable(false);
    self.chk.subscribe(function(newValue) {
        console.log (newValue);
        //Handle jQuery Mobile
        $("input[data-bind='checked: chk']").each(function(){
            if ($(this).is(':checked') != newValue)  {
                $(this).prop('checked', newValue).checkboxradio("refresh");
            }
        });
    });
}



ko.applyBindings(new myViewModel());

Here the jsFiddle: http://jsfiddle.net/9QSaY/

Upvotes: 2

Related Questions