AngularJS - Enlace de botones de radio a modelos con valores booleanos

199

Tengo un problema al vincular botones de radio a un objeto cuyas propiedades tienen valores booleanos. Estoy tratando de mostrar las preguntas del examen recuperadas de un recurso $.

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

Con este objeto de ejemplo, la propiedad "isUserAnswer: true" no hace que se seleccione el botón de opción. Si encapsulo los valores booleanos entre comillas, funciona.

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

Desafortunadamente, mi servicio REST trata esa propiedad como un valor booleano y será difícil cambiar la serialización JSON para encapsular esos valores entre comillas. ¿Hay otra forma de configurar el enlace del modelo sin cambiar la estructura de mi modelo?

Aquí está el jsFiddle que muestra objetos que no funcionan y que funcionan

peteallen
fuente

Respuestas:

376

El enfoque correcto en Angularjs es usar ng-valuepara valores sin cadena de modelos.

Modifique su código así:

<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: Directamente desde la boca del caballo.

kumarharsh
fuente
12
solo quería agregar una nota al margen importante: ng-value debe tener el valor sin las llaves {{}} Ejemplo: ng-value = "choice2.id" vs value = "{{choice2.id}}"
Andi
Sí, eso es correcto, ya que el valor ng se evalúa en ese ámbito
kumarharsh
@Andi gracias por esta nota al margen, ¡me ahorró algo de tiempo de depuración!
Roy Milder
3
¿Se refiere al Data- prefijo creo ... La Data- prefijo es hacer que el código HTML válido (aunque sin que también todos los navegadores modernos manejar correctamente el código HTML)
kumarharsh
66
Sé que la publicación es bastante antigua, pero ahora tengo el mismo problema. Pero cuando uso su solución y cambio los botones de radio, todos los que una vez fueron seleccionados son verdaderos y no vuelven a ser falsos. ¿Existe alguna solucion para esto? (el problema también existe en el violín de OP)
Dominik G
21

Ese es un enfoque extraño con isUserAnswer. ¿Realmente vas a enviar las tres opciones de vuelta al servidor, donde recorrerá cada una de ellas isUserAnswer == true? Si es así, puedes probar esto:

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

Alternativamente, recomendaría cambiar su táctica:

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

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

De esa manera, puede enviar de {{question1.userChoiceId}}vuelta al servidor.

Langdon
fuente
Gracias por su respuesta. Sé que tu segunda solución es ideal; sin embargo, la aplicación en realidad admite múltiples tipos de preguntas, incluidas las preguntas "marque todas las que correspondan", de ahí la razón del valor que se almacena en cada opción. Por lo que puedo decir, su primera solución funciona para actualizar el modelo después de realizar una selección, pero no para mostrar el modelo recuperado del servidor con una selección ya realizada.
peteallen
2
Ah cierto. Puede resolver eso usando ngChecked, excepto que tendrá que dejar de usar verdadero / falso como cadenas. ¿Puedes hacer eso? jsfiddle.net/hgxjv/6
Langdon
3
Si, eso funciona! Había intentado usar ngChecked antes, pero no había eliminado el atributo ngModel. No funcionó con esa configuración, y supuse que era porque ngChecked no era compatible con los botones de radio. Al eliminar el atributo ngModel y usar ngChecked y vincular ngClick a su función setChoiceForQuestion logra lo que estoy tratando de hacer. ¡Gracias por tu ayuda!
peteallen
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>
Ronel Gonzales
fuente
Creo que esto solo funciona porque se trueevalúa como verdadero. Si su ng-valuees una cadena, por ejemplo, y no una referencia a algo $scope, tendrá que poner esa cadena entre comillas. Ese fue el caso para mí.
Jason Swett
¡Esta es la mejor respuesta para mí! Gracias Ronel!
Gisway
ng-check no es necesario aquí siempre que ng-model esté definido
Nico Westerdale
7

Traté de cambiar value="true"a ng-value="true", y parece funcionar.

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

Además, para que ambas entradas funcionen en su ejemplo, tendría que dar un nombre diferente a cada entrada, por ejemplo, responsedebería convertirse en response1y response2.

seung
fuente
1
No, los nombres pueden ser iguales.
kumarharsh
0

La forma en que se configuran sus radios en el violín, compartiendo el mismo modelo, hará que solo el último grupo muestre una radio marcada si decide citar todos los valores verdaderos. Un enfoque más sólido implicará dar a los grupos individuales su propio modelo y establecer el valor como un atributo único de las radios, como el id:

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

Aquí hay una representación del nuevo html:

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

Y un violín.

rGil
fuente
0

si está usando una variable booleana para enlazar el botón de radio. por favor refiérase debajo del código de muestra

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