Как отобразить массив в виде списка переключателей?

Я хотел бы пройти через массив, который я определяю в своем Javascript, и отображать список переключателей. Мой код, который сейчас не работает, и он выглядит следующим образом (также на jsfiddle):

<div data-bind="foreach: options" >
    <div>
        <input type="radio" name="optionsGroup" data-bind="checked: selected" />
        <span data-bind="text: label"></span>
     </div>    
</div>
var optionsList = [
    {"value": "a","label": "apple"},
    {"value": "b","label": "banana"},
    {"value": "c","label": "carrot"}
];
function viewModel() {
    var self = this;
    self.options = optionsList;
    self.selected = ko.observable("a");
    self.selected.subscribe(function(newValue) {
        alert("new value is " + newValue);
    });
}
ko.applyBindings(new viewModel());

Если мой массив является частью html, тогда он отлично работает, см. это (или jsfiddle):

<div>
    <input type="radio" name="optionsGroup" value="a" data-bind="checked: selected"     />Apple
</div>
<div>
    <input type="radio" name="optionsGroup" value="b" data-bind="checked: selected" />Banana
</div>
<div>
     <input type="radio" name="optionsGroup" value="c" data-bind="checked: selected" />Carrot
</div>
<div data-bind="text: selected">
</div>
function viewModel() {
    var self = this;
    self.selected = ko.observable("a");
    self.selected.subscribe(function(newValue) {
        alert("new value is " + newValue);
    });
}    
ko.applyBindings(new viewModel());

Я получил это для работы, создав все html в моем javascript и работая с помощью флажков, но я не могу сгенерировать группу радиокнопков, используя итератор foreach.

Кто-нибудь получил пример, как мой первый, чтобы работать?

Ответ 1

Вот один из способов сделать это. Обратите внимание, что привязка attr должна предшествовать привязке checked.

var optionsList = [
    {"value": "a", "label": "apple"},
    {"value": "b", "label": "banana"},
    {"value": "c", "label": "carrot"}
];

function viewModel() {
    this.options = optionsList;
    this.selected = ko.observable("a");
}

ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<h3>Fruits</h3>
<div data-bind="foreach: options" >
  <label>
    <input type="radio"
           name="optionsGroup" 
           data-bind="attr: {value: value}, checked: $root.selected" />
    <span data-bind="text: label"></span>
  </label>    
</div>

<h3>Selected value:</h3>
<pre data-bind="text: ko.toJSON($root.selected)"></pre>

Ответ 2

Ваш код сообщает об этой ошибке:

Сообщение: ReferenceError: выбрано не определено;

Значение привязки: отмечено: выбрано

Вы определили selected на уровне модели представления, но ссылаетесь на него внутри foreach, поэтому Knockout.js ищет его на уровне параметров.

Изменить:

<div><input type="radio" name="optionsGroup" data-bind="checked: selected" />

в

<div><input type="radio" name="optionsGroup" data-bind="checked: $root.selected" />

$root.selected будет искать свойство selected на уровне модели представления.

ЗДЕСЬ - это модифицированный код.

Для получения дополнительной информации о псевдопеременных (например, $root) см. 3. Доступ к контекстам привязки к родителям.

Ответ 3

Чтобы иметь весь объект, лучше использовать checkedValue вместо attr: {value} следующим образом:

Fruits
<div data-bind="foreach: options" >
    <div><input type="radio" name="optionsGroup" data-bind="checkedValue: $data, checked: $root.selected" />
    <span data-bind="text: label"></span></div>    
</div>

Ответ 4

Вы код работает. Просто добавьте knockout.js в свой jsfiddle и установите документ "onDomready": http://screencast.com/t/DmTSgCoEUsxC