Question

I have a Checkbox that its using KnockoutJS binding. The value is assigned to the input element but I can't see the checkbox being checked, only if I manually click on it.

Behind the scenes the input element is working and getting the checked value to the property but becuase Im jQuery.uniforms.js to give a nice design to the forms then I guess that's why I'm not visually seeing the check on the checkbox.

<div class="inline">
   <input type="checkbox" data-bind='checked: permit.oneDayPermit' />
   <label>One Day Permit</label>
</div>

Im using jQuery.uniforms.js to give a nice design to the forms, so when inspecting the checkbox element I can see that a div and a span element are beign added to the code to make it look nicer:

<div class="checker">
  <span>
    <input type="checkbox" data-bind="checked: permit.oneDayPermit" value="[object Object]">
  </span>
</div>

When I click on the checkbox element to make it selected then the span element has a class named "checked":

<div class="checker">
  <span class="checked">
    <input type="checkbox" data-bind="checked: permit.oneDayPermit" value="[object Object]">
  </span>
</div>

Any clue on how can I solve this so the checkbox will get the check mark?

Appreciate any help.

Was it helpful?

Solution

Ok I'm pretty sure that you can use functions and methods in your bindings for KO. So for instance in checked you could add an anonymous function that sets the class of the parent above it. But rather you might want to bind your checked to a function in your ViewModel that can set the parent as well as the observable.

Lastly you could create a bindingHandler to nicely do this. The bindingHandler will be a custom action that will be applied initially and additionally upon any changes of the bound data. So when oneDayPermit experiences a change the update method will be fired. The bindingHandler will be sent a reference to the element (checkbox) as well as the binding, from here we can use jQuery to find its parent span and perform the addClass method on it.

The KO Code:

    ko.bindingHandlers.prettyCheck = {
        init: function (element, valueAccessor) {
            var value = valueAccessor();
            if (value()) {
                $(element).parent("span").addClass('checked');
            } else {
                $(element).parent("span").removeClass('checked');
            }
        },
        update: function (element, valueAccessor) {
            var value = valueAccessor();
            if (value()) {
                $(element).parent("span").addClass('checked');
            } else {
                $(element).parent("span").removeClass('checked');
            }
        }
    };

    function viewModel() {
        var self = this;
        self.oneDayPermit = ko.observable(false);
    }

    ko.applyBindings(new viewModel(), $("#checkerDiv")[0]);

Your HTML will look like this:

<div class="checker" id="checkerDiv">
  <span>
    <input type="checkbox" data-bind="prettyCheck: oneDayPermit, checked: oneDayPermit">
  </span>
</div>

Here's the fiddle: http://jsfiddle.net/jLqmc/21/

Alternately you could use a function instead of binding directly to an observable. Inside your function(which you could pass a reference of the element) you could toggle your observable and also perform jQuery operations on. You will see 3 parameters here but the first one is I forget. Its maybe something that is required by KO as a reference to the context and is not actually passed as a parameter. Anywho they two after are what is passed as parameters.

<div class="checker" id="checkerDiv">
  <span>
    <input type="checkbox" data-bind="checked: toggleCheck.bind($data, oneDayPermit, $(this))">
  </span>
</div>

In your VM

self.toggleCheck= function (binding, element) {
  //Toggle Observable and do your Element stuffs
}

OTHER TIPS

You can monkey-patch Knockout's built-in checked binding, like this:

ko.bindingHandlers.checked.update = (function () {
    var origialUpdate = ko.bindingHandlers.checked.update;
    return function (element, valueAccessor) {
        var parent = element.parentNode,
            checked = ko.unwrap(valueAccessor());

        origialUpdate.apply(this, arguments);

        if (parent.nodeName.toLowerCase() === "span") {
            ko.utils.toggleDomNodeCssClass(parent, "checked", checked);
        }
    };
})();

This snippet hijacks the update handler of the binding and toggles the checked class at the parent <span> element. No jQuery code necessary, Knockout has all the required utility functions.

You can implement a more elaborate version that does it with jQuery, though.

This way your binding code can stay the same.

http://jsfiddle.net/5TuTc/

After loading data in Permit add following code: $('#checkerDiv .checkboxes').uniform();

add class "checkboxes" or any other name to all the checkboxes that are binded.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top