Reputation: 16703
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
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
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