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, що показує непрацюючі та робочі об’єкти

Відповіді:


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>

Ref: Прямо з уст коня


12
просто хотів додати важливу сторону: - ng-value має мати значення без фігурних дужок {{}} Приклад: ng-value = "choice2.id" vs value = "{{choice2.id}}"
Andi

Так, це правильно, оскільки значення ng оцінюється в цій області
kumarharsh

@ Анді дякую за цю бічну записку, це врятувало мені деякий час налагодження!
Рой Мілдер

3
Ви маєте на увазі префікс даних, я думаю ... Префікс даних - це зробити HTML дійсним (хоча без цього також усі сучасні браузери правильно обробляють HTML)
kumarharsh

6
Я знаю, що посада досить стара, але в мене зараз така ж проблема. Але коли я використовую ваше рішення і змінюю перемикачі, все, що було вибрано, є істинним, і вони не перемикаються на хибні. Чи є для цього рішення? (Проблема також існує у Скрипці ОП)
Домінік G

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, вам доведеться поставити цю лапку в лапки. Так було для мене.
Jason Swett

Це найкраща відповідь для мене! Спасибі, Ронель!
Gisway

тут не потрібно перевіряти ng, доки визначено ng-модель
Nico Westerdale

7

Я спробував перейти value="true"на ng-value="true", і, здається, працює.

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

Крім того, щоб обидва входи працювали у вашому прикладі, вам слід було б вказати різні назви кожному вводу - наприклад, responseслід стати response1і response2.


1
Ні, імена можуть бути однаковими.
kumarharsh


0

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

І скрипка.


0

якщо ви використовуєте булеву змінну для прив'язки перемикача. зверніться нижче до зразкового коду

<div ng-repeat="book in books"> 
<input type="radio" ng-checked="book.selected"  
ng-click="function($event)">                        
</div>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.