【问题标题】:AngularJS - Binding radio buttons to models with boolean valuesAngularJS - 将单选按钮绑定到具有布尔值的模型
【发布时间】:2013-06-02 22:37:53
【问题描述】:

我在将单选按钮绑定到属性具有布尔值的对象时遇到问题。我正在尝试显示从 $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 序列化以将这些值封装在引号中。是否有其他方法可以在不更改模型结构的情况下设置模型绑定?

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

【问题讨论】:

    标签: angularjs data-binding model radio


    【解决方案1】:

    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>
    

    参考:Straight from the horse's mouth

    【讨论】:

    • 只是想添加一个重要的旁注:ng-value 必须具有不带花括号 {{}} 的值 示例:ng-value="choice2.id" vs value="{{选择2.id}}"
    • 是的,这是正确的,因为 ng-value 是在该范围内评估的
    • @Andi 感谢这个旁注,它为我节省了一些调试时间!
    • 你的意思是 data- 前缀我认为...... data- 前缀是为了使 HTML 有效(尽管没有它也是所有现代的浏览器正确处理 HTML)
    • 我知道这篇文章已经很老了,但我现在遇到了同样的问题。但是,当我使用您的解决方案并更改单选按钮时,所有曾经被选中的按钮都为真,它们不会切换回假。有解决方案吗? (问题也存在于 OP 的 Fiddle 中)
    【解决方案2】:

    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}} 发送回服务器。

    【讨论】:

    • 感谢您的回复。我知道您的第二种解决方案是理想的;但是,该应用程序实际上支持多种类型的问题,包括“检查所有适用的”问题 - 因此每个选项都存储值的原因。据我所知,您的第一个解决方案适用于在做出选择后更新模型,但不适用于显示从服务器检索到的模型并已做出选择。
    • 啊,真的。您可以使用ngChecked 来解决这个问题,除非您必须摆脱使用真/假作为字符串。你能做到吗? jsfiddle.net/hgxjv/6
    • 是的,这行得通!我之前尝试过使用 ngChecked,但没有删除 ngModel 属性。它不适用于该配置,我认为这是因为 ngChecked 与单选按钮不兼容。删除 ngModel 属性并使用 ngChecked 并将 ngClick 绑定到您的 setChoiceForQuestion 函数可以实现我想要做的事情。感谢您的帮助!
    【解决方案3】:
     <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 中某些内容的引用,那么您必须将该字符串放在引号中。我就是这样。
    • 这对我来说是最好的答案!谢谢,罗内尔!
    • 这里不需要ng-checked,只要定义了ng-model
    【解决方案4】:

    我尝试将value="true" 更改为ng-value="true",它似乎有效。

    &lt;input type="radio" name="response2" data-ng-model="choice.isUserAnswer" ng-value="true" /&gt;

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

    【讨论】:

    • 不,名称可以相同。
    【解决方案5】:

    你可以看看这个:

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

    这个人写了一个自定义指令来解决“true”和“false”是字符串而不是布尔值的问题。

    【讨论】:

      【解决方案6】:

      如果您决定引用所有真实值,您的收音机在小提琴中的设置方式 - 共享相同的型号 - 将导致只有最后一组显示选中的收音机。更可靠的方法是为各个组提供自己的模型,并将值设置为无线电的唯一属性,例如 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>
      

      And a fiddle.

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

          猜你喜欢
          • 2015-04-27
          • 1970-01-01
          • 2023-03-18
          • 2021-12-24
          • 1970-01-01
          • 2014-01-21
          • 2011-02-16
          • 1970-01-01
          • 2013-06-29
          相关资源
          最近更新 更多