2

I'm using a template binding to render a set of radio buttons. There is also a css binding on the element.

When a radio button is clicked, the viewmodel & view are are updated, but the checked state of the radio button is lost. Is there a work around for this?

http://jsfiddle.net/d3YJc/1/

<div data-bind="with: point">
    <div data-bind="template: { name: 'template1', data: $data }, css: { 'has-warning': hasAlarm }"></div>
</div>

<script type="text/template" id="template1">
    <!-- ko foreach: choices -->
    <label>
        <input type="radio" data-bind="checked: $parent.value, value: $data" name="test" />
        <span data-bind="text: $data"></span>        
    </label><br/>
    <!-- /ko -->    
    <span data-bind="visible: hasAlarm">Abnormal!</span>
</script>
Homer
  • 7,594
  • 14
  • 69
  • 109
  • Strangely if you use the template's `foreach` options it works: http://jsfiddle.net/FTnCd/ By the way it is working in your sample as well if you click twice on a label. – nemesv Jul 24 '13 at 19:33
  • 1
    If you are using checkbox-es it is also not working: http://jsfiddle.net/RjH3E/. At this point I would say that you have found a bug but it seems it was fixed in version 3.0: http://jsfiddle.net/Ne48f/ So you should upgrade to 3.0 beta or you use my workaround from my previous comment. – nemesv Jul 24 '13 at 19:48
  • I think it might have to do with the fact that all bindings are reevaluated each time. If so, maybe Knockout v3.0 will fix it. – Homer Jul 24 '13 at 19:50
  • @nemesv You should add that as the answer. It is definitely a bug. – Kyeotic Jul 24 '13 at 20:10
  • @nemesv It works with `foreach` because it doesn't rerender if the data is the same, but with `data`, it does re-render. The root cause, though, is that all bindings for an element are updated together (before 3.0). – Michael Best Jul 24 '13 at 20:26
  • Actually the problem is a little different. I'll add an answer. – Michael Best Jul 24 '13 at 20:32

1 Answers1

4

The problem is with the order of the checked and value bindings. The checked binding uses the element's value to determine whether it should be checked or not. When the element is first bound, the value is set by the value binding after the checked binding is initialized. So the simplest fix is to re-order the bindings. Also I'd suggest you use the attr binding instead of value since value has extra overhead (it's a two-way binding designed for text boxes).

data-bind="attr: {value: $data}, checked: $parent.value"

http://jsfiddle.net/mbest/d3YJc/2/

Knockout 3.0 fixes the order problem also (in addition to the rendering issue mentioned in the comments), so that's another way to solve this.

Michael Best
  • 16,623
  • 1
  • 37
  • 70