AngularJS - привязка переключателей к моделям с логическими значениями

199

У меня проблема с привязкой переключателей к объекту, свойства которого имеют логические значения. Я пытаюсь отобразить вопросы экзамена, полученные из ресурса $.

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 для инкапсуляции этих значений в кавычках. Есть ли другой способ установить привязку модели без изменения структуры моей модели?

Вот jsFiddle, показывающий нерабочие и рабочие объекты

peteallen
источник

Ответы:

376

Правильный подход в 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>

Ссылка: прямо изо рта лошади

kumarharsh
источник
12
просто хотел добавить важное примечание: ng-значение должно иметь значение без фигурных скобок {{}} Пример: ng-value = "choice2.id" vs value = "{{choice2.id}}"
Andi
Да, это правильно, так как значение ng оценивается в этой области
kumarharsh
@Анди спасибо за эту заметку, это сэкономило мне время на отладку!
Рой Милдер
3
Вы имеете в виду префикс данных, я думаю ... Префикс данных состоит в том, чтобы сделать HTML верным (хотя без этого также все современные браузеры корректно обрабатывают HTML)
kumarharsh
6
Я знаю, что пост довольно старый, но сейчас у меня такая же проблема. Но когда я использую ваше решение и меняю переключатели, все, что когда-то было выбрано, являются истинными, и они не переключаются обратно в ложные. Есть ли решение для этого? (проблема также существует в скрипке ОП)
Доминик Г.
21

Это странный подход с 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}}обратно на сервер.

Лэнгдон
источник
Спасибо за ваш ответ. Я знаю, что ваше второе решение идеально; тем не менее, приложение на самом деле поддерживает несколько типов вопросов, в том числе вопросы «отметьте все, что применимо» - отсюда и причина сохранения значения при каждом выборе. Из того, что я могу сказать, ваше первое решение работает для обновления модели после выбора, но не для отображения модели, полученной с сервера с уже сделанным выбором.
peteallen
2
Ах, правда. Вы можете решить это с помощью ngChecked, за исключением того, что вам придется отказаться от использования true / false в качестве строк. Вы можете сделать это? jsfiddle.net/hgxjv/6
Лэнгдон
3
Да, это работает! Я пытался использовать ngChecked раньше, но не удалил атрибут ngModel. Он не работал с этой конфигурацией, и я предположил, что это потому, что ngChecked не был совместим с переключателями. Удаление атрибута ngModel и использование ngChecked и привязка ngClick к вашей функции setChoiceForQuestion позволяет добиться того, что я пытаюсь сделать. Спасибо за помощь!
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>
Ронель Гонсалес
источник
Я думаю, что это работает только потому, что trueоценивается как правда. Если вы ng-value, например, строка, а не ссылка на что-то внутри $scope, вам придется поместить эту строку в кавычки. Это был случай для меня.
Джейсон Светт
Это лучший ответ для меня! Спасибо, Ронель!
Gisway
Проверка ng здесь не нужна, если определена модель ng
Нико Вестердейл,
7

Я попытался перейти value="true"на ng-value="true", и это похоже на работу.

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

Кроме того, чтобы оба входа работали в вашем примере, вам нужно было бы дать разные имена каждому входу - например, responseдолжен стать response1и response2.

Seung
источник
1
Нет, имена могут быть одинаковыми.
kumarharsh
1

Вы могли бы взглянуть на это:

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

Этот парень написал пользовательскую директиву, чтобы обойти проблему, что «true» и «false» являются строками, а не логическими значениями.

Карен Зиллес
источник
0

То, как ваши радиостанции настроены в скрипке - совместно используют одну и ту же модель - заставит только последнюю группу показывать проверенное радио, если вы решите процитировать все истинные значения. Более надежный подход будет предусматривать предоставление отдельным группам их собственной модели и задание значения в качестве уникального атрибута радиостанций, например 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>

И скрипка.

rGil
источник
0

если вы используете логическую переменную для привязки переключателя. пожалуйста, обратитесь ниже пример кода

<div ng-repeat="book in books"> 
<input type="radio" ng-checked="book.selected"  
ng-click="function($event)">                        
</div>
Сахития М
источник