andrew
andrew

Reputation: 9583

dynamic radio button behaviour with knockout js

I have a button to create radio buttons like this:

<input value="&uparrow;" type="button" data-bind=" click: moveUp"/>
<input value="&downarrow;" type="button" data-bind="click: moveDown"/>
<input data-bind="value: selectedradio" />
<div data-bind="foreach: radios">
    <div data-bind="attr:{id:radioid} ">
       <input type="radio" name="group" data-bind="value:radioid, checked:$parent.selectedradio"/>
     </div>
</div>
<div>
     <input type="button" value="+" data-bind="click: addRadio"/>
</div>

when the radio buttons are created they are each assigned a unique index and i have bound the checked attribute to a property on the parent called selectedradio

I am able to modify selectedradio though an html input and the selected radio will change but If I modify the value progmmatically it will not.

I created a fiddle here: http://jsfiddle.net/8vVeU/

here is the javascript for reference:

function Radio(id){
    this.radioid = ko.observable(id);
}

 function ViewModel() {
        var self = this;
        self.selectedradio = ko.observable(0);
        self.radios = ko.observableArray([new Radio(0),new Radio(1),new Radio(2),new Radio(3)]);

        self.addRadio = function() {
            self.radios.push(new Radio());
            self.reIndex();
         };
         self.moveUp = function() {
            self.selectedradio(self.selectedradio()-1)
            self.reIndex();
          };
        self.moveDown = function() {
            self.selectedradio(self.selectedradio()+1)
            self.reIndex();
          };

        self.reIndex = function() {
            $.each(self.radios(), function(i, r) {
                r.radioid(i);             
          });
        }


}
ko.applyBindings(new ViewModel());

How can I resolve this issue?

Upvotes: 3

Views: 2646

Answers (1)

nemesv
nemesv

Reputation: 139758

In the case of radio buttons the checked binding by default compares the input's value attribute - which is a string - to the model property.

So you need to store strings in your selectedradio :

self.moveUp = function(r) {
    r=parseInt(r,10);
    self.selectedradio((parseInt(self.selectedradio())-1).toString())
    self.reIndex();
};
self.moveDown = function(r) {
    r=parseInt(r,10);
    self.selectedradio((parseInt(self.selectedradio())+1).toString())
    self.reIndex();
};

It works with the textbox because it will fill in the selectedradio with the entered string.

Demo JSFiddle.

Or you can change the default behavior and you can tell KO to use a different property as the checkbox's value with the checkedValue option:

<input type="radio" name="group" data-bind="value:radioid, 
       checked:$parent.selectedradio, checkedValue: radioid"/>

In this case you don't need to alter your moveUp and moveDown methods because now the selectedradio will always contain integers however because your textbox still sets the selectedradio to string it won't work any more.

Demo JSFiddle.

Upvotes: 4

Related Questions