AngularJS - Powiązanie przycisków opcji z modelami o wartościach boolowskich

199

Mam problem z powiązaniem przycisków opcji z obiektem, którego właściwości mają wartości logiczne. Próbuję wyświetlić pytania egzaminacyjne pobrane z zasobu $.

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

W tym przykładowym obiekcie właściwość „isUserAnswer: true” nie powoduje wybrania przycisku opcji. Jeśli hermetyzuję wartości boolowskie w cudzysłowach, to działa.

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

Niestety moja usługa REST traktuje tę właściwość jako wartość logiczną i ciężko będzie zmienić serializację JSON, aby zawrzeć te wartości w cudzysłowach. Czy istnieje inny sposób skonfigurowania wiązania modelu bez zmiany struktury mojego modelu?

Oto jsFiddle pokazujący niedziałające i pracujące obiekty

Peteallen
źródło

Odpowiedzi:

376

Prawidłowe podejście w Angularjs polega na stosowaniu ng-valuew przypadku ciągów wartości modeli.

Zmodyfikuj kod w następujący sposób:

<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: Prosto z pyska konia

kumarharsh
źródło
12
chciałem tylko dodać ważną notatkę: wartość-ng musi mieć wartość bez nawiasów klamrowych {{}} Przykład: ng-wartość = "choice2.id" vs wartość = "{{choice2.id}}"
Andi
Tak, to prawda, ponieważ wartość ng jest oceniana w tym zakresie
kumarharsh
@Andi dziękuję za tę notatkę dodatkową, dzięki czemu zaoszczędziłem trochę czasu na debugowanie!
Roy Milder
3
Masz na myśli prefiks danych ... Myślę, że prefiks danych ma sprawić, że HTML będzie poprawny (chociaż bez tego również wszystkie nowoczesne przeglądarki poprawnie obsługują HTML)
kumarharsh
6
Wiem, że post jest dość stary, ale teraz mam ten sam problem. Ale kiedy używam twojego rozwiązania i zmieniam przyciski opcji, wszystkie raz wybrane są prawdziwe i nie przełączają się ponownie na false. Czy jest na to rozwiązanie? (problem występuje również w skrzypcach OP)
Dominik G
21

To dziwne podejście isUserAnswer. Czy naprawdę zamierzasz odesłać wszystkie trzy opcje z powrotem do serwera, na którym będzie on przechodził przez każdą z nich w poszukiwaniu isUserAnswer == true? Jeśli tak, możesz spróbować:

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

Ewentualnie polecam zmianę halsu:

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

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

W ten sposób możesz po prostu odesłać z {{question1.userChoiceId}}powrotem na serwer.

Langdon
źródło
Dzięki za twoją odpowiedź. Wiem, że twoje drugie rozwiązanie jest idealne; jednak aplikacja obsługuje wiele rodzajów pytań, w tym pytania „sprawdź wszystkie, które dotyczą” - stąd przyczyna przechowywania wartości dla każdego wyboru. Z tego, co mogę powiedzieć, twoje pierwsze rozwiązanie działa na aktualizację modelu po dokonaniu wyboru, ale nie na wyświetlaniu modelu pobranego z serwera z już dokonanym wyborem.
peteallen
2
Ach, prawda. Możesz rozwiązać ten problem, używając ngChecked, z wyjątkiem tego, że będziesz musiał zerwać z użyciem wartości true / false jako ciągów. Możesz to zrobić? jsfiddle.net/hgxjv/6
Langdon
3
Tak, to działa! Próbowałem wcześniej użyć ngChecked, ale nie usunąłem atrybutu ngModel. Nie działało z tą konfiguracją i założyłem, że było tak, ponieważ ngChecked nie był kompatybilny z przyciskami radiowymi. Usunięcie atrybutu ngModel i użycie ngChecked i powiązanie ngClick z funkcją setChoiceForQuestion osiąga to, co próbuję zrobić. Dziękuję za pomoc!
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
źródło
Myślę, że to działa tylko dlatego, że trueocenia się na prawdę. Jeśli Twój ng-valueciąg znaków jest na przykład ciągiem, a nie odniesieniem do czegoś $scope, musisz wpisać ten ciąg w cudzysłów. Tak było w moim przypadku.
Jason Swett
To dla mnie najlepsza odpowiedź! Dzięki, Ronel!
Gisway
ng-sprawdzone nie jest tutaj potrzebne, dopóki zdefiniowany jest model ng
Nico Westerdale,
7

Próbowałem zmieniających value="true"się ng-value="true"i wydaje się do pracy.

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

Ponadto, aby oba wejścia działały w twoim przykładzie, musisz nadać każdemu z nich inną nazwę - np. responsePowinno się stać response1i response2.

seung
źródło
1
Nie, nazwy mogą być takie same.
kumarharsh
0

Sposób skonfigurowania radia w skrzypcach - współdzielenie tego samego modelu - spowoduje, że tylko ostatnia grupa pokaże sprawdzone radio, jeśli zdecydujesz się zacytować wszystkie prawdziwe wartości. Bardziej solidne podejście będzie polegało na nadaniu poszczególnym grupom własnego modelu i ustawieniu wartości jako unikalnego atrybutu radiotelefonów, takiego jak id:

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

Oto reprezentacja nowego html:

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

I skrzypce.

rGil
źródło
0

jeśli używasz zmiennej boolean do powiązania przycisku opcji. zapoznaj się z przykładowym kodem

<div ng-repeat="book in books"> 
<input type="radio" ng-checked="book.selected"  
ng-click="function($event)">                        
</div>
Sahitya M.
źródło