AngularJS-将单选按钮绑定到具有布尔值的模型


199

我在将单选按钮绑定到其属性具有布尔值的对象时遇到问题。我正在尝试显示从$ 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
        }]
};   

对于此示例对象,“ isUserAnswer:true”属性不会导致选中单选按钮。如果我将布尔值封装在引号中,则可以使用。

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"
        }]
};   

不幸的是,我的REST服务将该属性视为布尔值,并且很难更改JSON序列化以将这些值封装在引号中。还有另一种方法可以设置模型绑定而不更改模型的结构吗?

这是显示非工作对象和工作对象的jsFiddle

Answers:


376

Angularjs中正确的方法是对ng-value模型的非字符串值使用。

像这样修改您的代码:

<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>

参考:从马口直行


12
只是想添加一个重要的注释:ng-value必须具有不带花括号{{}}的值例如:ng-value =“ choice2.id” vs value =“ {{choice2.id}}”
安迪

是的,这是正确的,因为在该范围内评估了ng值
kumarharsh 2014年

@Andi感谢您的旁注,它为我节省了一些调试时间!
罗伊·米尔德

3
你指的是数据-前缀我想......的数据-前缀是使HTML有效的(虽然没有也所有现代浏览器处理HTML正确)
kumarharsh

6
我知道该职位已经很老了,但现在我遇到了同样的问题。但是,当我使用您的解决方案并更改单选按钮时,所有曾经选择的按钮都是真实的,并且它们不会切换回false。有解决方案吗?(OP的小提琴中也存在问题)
Dominik G

21

使用的方法很奇怪isUserAnswer。您是否真的要将所有三个选择都发送回服务器,服务器将在其中循环检查每个选项isUserAnswer == true?如果是这样,您可以尝试以下操作:

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;
};

另外,我建议您改变方法:

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

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

这样,您可以将其发送{{question1.userChoiceId}}回服务器。


感谢您的答复。我知道您的第二个解决方案是理想的;但是,该应用程序实际上支持多种类型的问题,包括“选中所有适用项”问题-因此,将值存储在每个选项中的原因。据我所知,您的第一个解决方案适用于在做出选择之后更新模型,但不适用于显示已经做出选择的从服务器检索到的模型。
peteallen 2013年

2
啊,是的。您可以使用来解决此问题ngChecked,除了必须摆脱使用true / false作为字符串的情况。你能做到吗?jsfiddle.net/hgxjv/6
兰登

3
是的,行得通!我之前曾尝试使用ngChecked,但没有删除ngModel属性。它不适用于该配置,我以为是ngChecked与单选按钮不兼容。删除ngModel属性并使用ngChecked并将ngClick绑定到setChoiceForQuestion函数可以实现我正在尝试做的事情。谢谢您的帮助!
peteallen 2013年

10
 <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>

我认为这仅适用于true评估为真。ng-value例如,如果您是一个字符串,而不是对中的引用$scope,则必须将该字符串用引号引起来。对我来说就是这样。
杰森·斯威特 Jason Swett)

这是对我最好的答案!谢谢,罗纳尔!
吉斯韦

只要定义了ng-model,就不需要ng-checked
Nico Westerdale

7

我尝试将更value="true"改为ng-value="true",但似乎可行。

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

另外,要使两个输入都能在您的示例中正常工作,您必须为每个输入指定不同的名称-例如,response应该变成response1response2


1
不,名称可以相同。
kumarharsh


0

如果您决定引用所有真实值,则在小提琴中设置收音机的方式(共享相同的模型)将仅使最后一组显示选中的收音机。一种更可靠的方法是为各个小组提供自己的模型,并将值设置为无线电的唯一属性,例如id:

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

这是新html的表示形式:

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

和一个小提琴。


0

如果您使用布尔变量绑定单选按钮。请参考下面的示例代码

<div ng-repeat="book in books"> 
<input type="radio" ng-checked="book.selected"  
ng-click="function($event)">                        
</div>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.