1

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

2
  • Really strange issue you're having. The only way I could get rid of the error was removing the for attribute of your label... May need to file a bug with knockout ;) Commented Sep 30, 2013 at 3:18
  • I have see that is link to the ID for the input checkbox that are different in order to link them to their label... Commented Sep 30, 2013 at 3:44

2 Answers 2

5

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/

Sign up to request clarification or add additional context in comments.

Comments

2

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/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.