Reputation: 633
I am trying to learn Knockout while building a fairly complex dynamic form which is styled using the jQuery plugin Uniform JS. Since Knockout is dynamically building parts of the form on the fly I need to make sure Uniform JS keeps up and styles the dynamically generated form elements.
After some searching I found a blog post titled "Knockout JS knockouts" by Mikhail Temkine explaining how to write a custom Knockout binding to solve the problem with Uniform styled checkboxes. The custom binding looks like this:
ko.bindingHandlers.checkedUniform = {
init: function (element, valueAccessor) {
ko.bindingHandlers.checked.init(element, valueAccessor);
},
update: function (element, valueAccessor) {
ko.bindingHandlers.checked.update(element, valueAccessor);
$.uniform.update($(element));
}
};
The simplified HTML looks something like this:
<ul data-bind="foreach: items">
<li data-bind="text: name, click: $root.editItem, css: {bold: bolded()}"></li>
</ul>
<div data-bind="with: selectedItem">
Edit list item: <input data-bind="value: name" />
Make it bold: <input type="checkbox" data-bind="checkedUniform: bolded />
</div>
The custom binding apparently uses the uniform.update()
method which is supposed to refresh the state of the styled checkboxes. Unfortunately it isn't working. The checkboxes are styled according to the selected Uniform design template, but as soon as the Knockout template is re-rendered (in this case when selectedItem
changes) the indicator showing whether the checkbox is ticked or not is lost. The checkboxes are still functional, you can click them to toggle their state, it's just that they always show up as unchecked.
I have created a simple jsFiddle to demonstrate the problem:
http://jsfiddle.net/tomas_eklund/RaSpK/1/
Upvotes: 3
Views: 1670
Reputation: 139788
Your styling get lost because when using the with
binding it replaces the DOM underneath when its value changes. So your initial $('input[type="checkbox"]').uniform();
won't be applied to the newly created checkboxes.
To solve this instead of generally apply the uniform
plugin move the initialization logic into your checkedUniform
init function (it will run once a binding applied to an element even if the element was just created by KO):
ko.bindingHandlers.checkedUniform = {
init: function (element, valueAccessor) {
ko.bindingHandlers.checked.init(element, valueAccessor);
$(element).uniform();
},
update: function (element, valueAccessor) {
ko.bindingHandlers.checked.update(element, valueAccessor);
$.uniform.update($(element));
}
};
Demo JSFiddle.
Upvotes: 2