AngularJS - Optionsfelder an Modelle mit Booleschen Werten binden

199

Ich habe ein Problem beim Binden von Optionsfeldern an ein Objekt, dessen Eigenschaften boolesche Werte haben. Ich versuche, Prüfungsfragen anzuzeigen, die aus einer $ -Ressource abgerufen wurden.

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

Bei diesem Beispielobjekt bewirkt die Eigenschaft "isUserAnswer: true" nicht, dass das Optionsfeld ausgewählt wird. Wenn ich die booleschen Werte in Anführungszeichen kapsle, funktioniert es.

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

Leider behandelt mein REST-Service diese Eigenschaft als Booleschen Wert, und es wird schwierig sein, die JSON-Serialisierung zu ändern, um diese Werte in Anführungszeichen zu setzen. Gibt es eine andere Möglichkeit, die Modellbindung einzurichten, ohne die Struktur meines Modells zu ändern?

Hier ist die jsFiddle, die nicht funktionierende und funktionierende Objekte zeigt

peteallen
quelle

Antworten:

376

Der richtige Ansatz in Angularjs besteht darin, ng-valuefür Nicht-String-Werte von Modellen zu verwenden.

Ändern Sie Ihren Code wie folgt:

<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: Direkt aus dem Maul des Pferdes

kumarharsh
quelle
12
Ich wollte nur eine wichtige Randnotiz hinzufügen: ng-value muss den Wert ohne geschweifte Klammern haben {{}} Beispiel: ng-value = "choice2.id" vs value = "{{choice2.id}}"
Andi
Ja, das ist richtig, da der ng-Wert in diesem Bereich ausgewertet wird
kumarharsh
@Andi danke für diese Randnotiz, es hat mir einige Zeit beim Debuggen gespart!
Roy Milder
3
Du meinst das Datenpräfix, denke ich ... Das Datenpräfix soll den HTML-
Code
6
Ich weiß, dass der Beitrag ziemlich alt ist, aber ich habe jetzt das gleiche Problem. Aber wenn ich Ihre Lösung verwende und die Optionsfelder ändere, sind alle einmal ausgewählten wahr und sie wechseln nicht zurück zu falsch. Gibt es dafür eine Lösung? (Problem besteht auch in OP's Fiddle)
Dominik G
20

Das ist ein seltsamer Ansatz isUserAnswer. Werden Sie wirklich alle drei Auswahlmöglichkeiten an den Server zurücksenden, wo er jede Prüfung durchläuft isUserAnswer == true? Wenn ja, können Sie Folgendes versuchen:

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

Alternativ würde ich empfehlen, Ihre Richtung zu ändern:

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

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

Auf diese Weise können Sie einfach {{question1.userChoiceId}}an den Server zurücksenden.

Langdon
quelle
Vielen Dank für Ihre Antwort. Ich weiß, dass Ihre zweite Lösung ideal ist. Die App unterstützt jedoch tatsächlich mehrere Arten von Fragen, einschließlich der Frage "Alle zutreffenden prüfen" - daher der Grund dafür, dass der Wert bei jeder Auswahl gespeichert wird. Soweit ich das beurteilen kann, funktioniert Ihre erste Lösung zum Aktualisieren des Modells nach einer Auswahl, nicht jedoch zum Anzeigen des vom Server abgerufenen Modells mit einer bereits getroffenen Auswahl.
Peteallen
2
Ah, stimmt. Sie können dies mithilfe von beheben ngChecked, es sei denn, Sie müssen sich von der Verwendung von true / false als Zeichenfolgen lösen . Können Sie das tun? jsfiddle.net/hgxjv/6
Langdon
3
Ja das funktioniert Ich hatte zuvor versucht, ngChecked zu verwenden, aber das Attribut ngModel nicht entfernt. Mit dieser Konfiguration funktionierte es nicht und ich hatte angenommen, dass ngChecked nicht mit Optionsfeldern kompatibel war. Durch Entfernen des ngModel-Attributs und Verwenden von ngChecked und Binden von ngClick an Ihre setChoiceForQuestion-Funktion wird das erreicht, was ich versuche. Danke für Ihre Hilfe!
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
quelle
Ich denke das funktioniert nur weil true es als wahr bewertet wird. Wenn ng-valuees sich beispielsweise um eine Zeichenfolge handelt und nicht um einen Verweis auf etwas in $scope, müssen Sie diese Zeichenfolge in Anführungszeichen setzen. Das war bei mir der Fall.
Jason Swett
Das ist die beste Antwort für mich! Danke, Ronel!
Gisway
ng-geprüft wird hier nicht benötigt, solange ng-Modell definiert ist
Nico Westerdale
7

Ich habe versucht , zu ändern value="true"zu ng-value="true", und es scheint zu funktionieren.

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

Damit beide Eingaben in Ihrem Beispiel funktionieren, müssen Sie jeder Eingabe einen anderen Namen geben - z . B. responsesollte response1und werden response2.

seung
quelle
1
Nein, Namen können gleich sein.
Kumarshar
0

Die Art und Weise, wie Ihre Funkgeräte in der Geige eingerichtet sind und dasselbe Modell verwenden, führt dazu, dass nur die letzte Gruppe ein geprüftes Funkgerät anzeigt, wenn Sie alle wahrheitsgemäßen Werte angeben. Ein soliderer Ansatz besteht darin, den einzelnen Gruppen ein eigenes Modell zu geben und den Wert als eindeutiges Attribut der Funkgeräte festzulegen, z. B. die ID:

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

Hier ist eine Darstellung des neuen HTML:

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

Und eine Geige.

rGil
quelle
0

Wenn Sie eine boolesche Variable verwenden, um das Optionsfeld zu binden. Bitte beziehen Sie sich auf den folgenden Beispielcode

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