peteallen
peteallen

Reputation: 2553

AngularJS - Binding radio buttons to models with boolean values

I am having a problem binding radio buttons to an object whose properties have boolean values. I am trying to display exam questions retrieved from a $resource.

HTML:

<label data-ng-repeat="choice in question.choices">
  <input type="radio" name="response" data-ng-model="choice.isUserAnswer" value="true" />
  {{choice.text}}
</label>

JS:

$scope.question = {
    questionText: "This is a test question.",
    choices: [{
            id: 1,
            text: "Choice 1",
            isUserAnswer: false
        }, {
            id: 2,
            text: "Choice 2",
            isUserAnswer: true
        }, {
            id: 3,
            text: "Choice 3",
            isUserAnswer: false
        }]
};   

With this example object, the "isUserAnswer: true" property does not cause the radio button to be selected. If I encapsulate the boolean values in quotes, it works.

JS:

$scope.question = {
    questionText: "This is a test question.",
    choices: [{
            id: 1,
            text: "Choice 1",
            isUserAnswer: "false"
        }, {
            id: 2,
            text: "Choice 2",
            isUserAnswer: "true"
        }, {
            id: 3,
            text: "Choice 3",
            isUserAnswer: "false"
        }]
};   

Unfortunately my REST service treats that property as a boolean and it will be difficult to change the JSON serialization to encapsulate those values in quotes. Is there another way to set up the model binding without changing the structure of my model?

Here's the jsFiddle showing non-working and working objects

Upvotes: 206

Views: 229291

Answers (7)

Ronel Gonzales
Ronel Gonzales

Reputation: 125

 <label class="rate-hit">
     <input type="radio" ng-model="st.result" ng-value="true" ng-checked="st.result">
     Hit
 </label>
 &nbsp;&nbsp;
 <label class="rate-miss">
     <input type="radio" ng-model="st.result" ng-value="false" ng-checked="!st.result">
     Miss
 </label>

Upvotes: 12

Sahitya M
Sahitya M

Reputation: 11

if you are using boolean variable to bind the radio button. please refer below sample code

<div ng-repeat="book in books"> 
<input type="radio" ng-checked="book.selected"  
ng-click="function($event)">                        
</div>

Upvotes: 0

kumarharsh
kumarharsh

Reputation: 19629

The correct approach in Angularjs is to use ng-value for non-string values of models.

Modify your code like this:

<label data-ng-repeat="choice in question.choices">
  <input type="radio" name="response" data-ng-model="choice.isUserAnswer" data-ng-value="true" />
  {{choice.text}}
</label>

Ref: Straight from the horse's mouth

Upvotes: 392

seung
seung

Reputation: 436

I tried changing value="true" to ng-value="true", and it seems to work.

<input type="radio" name="response2" data-ng-model="choice.isUserAnswer" ng-value="true" />

Also, to get both inputs to work in your example, you'd have to give different name to each input -- e.g. response should become response1 and response2.

Upvotes: 9

Karen Zilles
Karen Zilles

Reputation: 7671

You might take a look at this:

https://github.com/michaelmoussa/ng-boolean-radio/

This guy wrote a custom directive to get around the issue that "true" and "false" are strings, not booleans.

Upvotes: 1

rGil
rGil

Reputation: 3719

The way your radios are set up in the fiddle - sharing the same model - will cause only the last group to show a checked radio if you decide to quote all of the truthy values. A more solid approach will involve giving the individual groups their own model, and set the value as a unique attribute of the radios, such as the id:

$scope.radioMod = 1;
$scope.radioMod2 = 2;

Here is a representation of the new html:

<label data-ng-repeat="choice2 in question2.choices">
            <input type="radio" name="response2" data-ng-model="radioMod2" value="{{choice2.id}}"/>
                {{choice2.text}}
        </label>

And a fiddle.

Upvotes: 0

Langdon
Langdon

Reputation: 20073

That's an odd approach with isUserAnswer. Are you really going to send all three choices back to the server where it will loop through each one checking for isUserAnswer == true? If so, you can try this:

http://jsfiddle.net/hgxjv/4/

HTML:

<input type="radio" name="response" value="true" ng-click="setChoiceForQuestion(question1, choice)"/>

JavaScript:

$scope.setChoiceForQuestion = function (q, c) {
    angular.forEach(q.choices, function (c) {
        c.isUserAnswer = false;
    });

    c.isUserAnswer = true;
};

Alternatively, I'd recommend changing your tack:

http://jsfiddle.net/hgxjv/5/

<input type="radio" name="response" value="{{choice.id}}" ng-model="question1.userChoiceId"/>

That way you can just send {{question1.userChoiceId}} back to the server.

Upvotes: 21

Related Questions