AngularJS - Associare i pulsanti di opzione ai modelli con valori booleani


199

Sto riscontrando un problema nel collegare i pulsanti di opzione a un oggetto le cui proprietà hanno valori booleani. Sto cercando di visualizzare le domande d'esame recuperate da una risorsa $.

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 questo oggetto di esempio, la proprietà "isUserAnswer: true" non determina la selezione del pulsante di opzione. Se incapsulo i valori booleani tra virgolette, funziona.

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

Sfortunatamente il mio servizio REST tratta quella proprietà come booleana e sarà difficile cambiare la serializzazione JSON per incapsulare questi valori tra virgolette. Esiste un altro modo per impostare l'associazione del modello senza modificare la struttura del mio modello?

Ecco il jsFiddle che mostra oggetti non funzionanti e funzionanti

Risposte:


376

L'approccio corretto in Angularjs è utilizzare ng-valueper valori non stringa di modelli.

Modifica il tuo codice in questo modo:

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

Rif: Direttamente dalla bocca del cavallo


12
volevo solo aggiungere una nota a margine importante: ng-value deve avere il valore senza parentesi graffe {{}} Esempio: ng-value = "choice2.id" vs value = "{{choice2.id}}"
Andi

Sì, è corretto, poiché il valore ng viene valutato in
quell'ambito

@Andi grazie per questa nota a margine, mi ha fatto risparmiare un po 'di tempo nel debug!
Roy Milder,

3
Intendi il prefisso dei dati, penso ... Il prefisso dei dati è di rendere valido l'HTML (anche se senza quello anche tutti i browser moderni gestiscono correttamente l'HTML)
kumarharsh,

6
So che il post è piuttosto vecchio ma ora ho lo stesso problema. Ma quando uso la tua soluzione e cambio i pulsanti di opzione, tutti quelli che erano stati selezionati sono veri e non tornano a essere falsi. C'è una soluzione per questo? (il problema esiste anche nel violino di OP)
Dominik G,

21

È un approccio strano con isUserAnswer. Hai davvero intenzione di rinviare tutte e tre le scelte al server dove eseguirà il ciclo di ciascuna verifica per isUserAnswer == true? In tal caso, puoi provare questo:

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

In alternativa, consiglierei di cambiare virata:

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

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

In questo modo puoi semplicemente rispedire {{question1.userChoiceId}}al server.


Grazie per la risposta. So che la tua seconda soluzione è l'ideale; tuttavia, l'app supporta effettivamente diversi tipi di domande, tra cui domande "controlla tutto ciò che si applica", quindi il motivo per cui il valore viene archiviato su ogni scelta. Da quello che posso dire, la tua prima soluzione funziona per l'aggiornamento del modello dopo aver effettuato una selezione, ma non per visualizzare il modello recuperato dal server con una selezione già effettuata.
peteallen,

2
Ah vero. Puoi risolverlo usando ngChecked, tranne che dovrai interrompere l'utilizzo di true / false come stringhe. Puoi farlo? jsfiddle.net/hgxjv/6
Langdon

3
Sì, funziona! Avevo provato a utilizzare ngChecked prima, ma non avevo rimosso l'attributo ngModel. Non funzionava con quella configurazione e avevo supposto che fosse perché ngChecked non era compatibile con i pulsanti di opzione. La rimozione dell'attributo ngModel e l'utilizzo di ngChecked e l'associazione ngClick alla funzione setChoiceForQuestion consente di ottenere ciò che sto cercando di fare. Grazie per l'aiuto!
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>

Penso che questo funzioni solo perché truevaluta vero. Se la tua ng-valueè una stringa, ad esempio, e non un riferimento a qualcosa in $scope, dovrai mettere quella stringa tra virgolette. Questo è stato il caso per me.
Jason Swett,

Questa è la risposta migliore per me! Grazie Ronel!
Gisway,

ng-checked non è necessario qui finché viene definito ng-model
Nico Westerdale,

7

Ho provato a cambiare value="true"in ng-value="true", e sembra funzionare.

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

Inoltre, per far funzionare entrambi gli input nel tuo esempio, dovresti assegnare un nome diverso a ciascun input, ad esempio responsedovrebbe diventare response1e response2.


1
No, i nomi possono essere gli stessi.
Kumarharsh,


0

Il modo in cui le tue radio sono impostate nel violino - condividendo lo stesso modello - farà sì che solo l'ultimo gruppo mostri una radio controllata se decidi di citare tutti i valori di verità. Un approccio più solido prevede di assegnare ai singoli gruppi il proprio modello e di impostare il valore come attributo univoco delle radio, come l'id:

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

Ecco una rappresentazione del nuovo HTML:

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

E un violino.


0

se si utilizza la variabile booleana per associare il pulsante di opzione. si prega di fare riferimento sotto il codice di esempio

<div ng-repeat="book in books"> 
<input type="radio" ng-checked="book.selected"  
ng-click="function($event)">                        
</div>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.