3

チェックボックスとラジオボタンのデータ構造は同じです。チェックボックスをオンにすると、正しいブール値(「選択された」変数)が返されます。

ただし、ラジオボタンをチェックすると、「選択済み」は常に「値」(整数)に変わります。

また、'chosen' == trueであっても、ラジオボタンは最初は「チェック」されません。

Javascript:

function attributeValueViewModel(data) {
    var self = this;
    self.id = ko.observable(data.id);
    self.attributeID = ko.observable(data.attributeID);
    self.value = ko.observable(data.value);
    self.chosen = ko.observable(data.chosen);
}

function viewModel() {
    var self = this;
    self.attributeValues1 = ko.observableArray([]);
    self.attributeValues2 = ko.observableArray([]);
    self.addToList = function(data) {
        ko.utils.arrayForEach(data, function(item) {           
            self.attributeValues1.push(new attributeValueViewModel(item));
            self.attributeValues2.push(new attributeValueViewModel(item));
        });
    };
}

var arr = [
    {
        "id": 55,
        "attributeID": 28,
        "value": "Yes",
        "chosen": false,
    },
    {
        "id": 56,
        "attributeID": 28,
        "value": "No",
        "chosen": true,
    },
    {
        "id": 62,
        "attributeID": 28,
        "value": "Maybe",
        "chosen": false,
    }
];

var vm = new viewModel();
ko.applyBindings(vm);
vm.addToList(arr);

HTML

<b>Checkbox:</b>
<div id="test1">
    <span data-bind="foreach: attributeValues1()">
    <input type="checkbox" data-bind="value: id(), checked: chosen, attr: { name: 'test1' }" />
    <span data-bind="text: value()"></span>
    <span data-bind="text: chosen()"></span>
    </span>
</div>
<br />
<b>Radio:</b>
<div id="test2">
    <span data-bind="foreach: attributeValues2()">
    <input type="radio" data-bind="value: id(), checked: chosen, attr: { name: 'test2' }" />
    <span data-bind="text: value()"></span>
    <span data-bind="text: chosen()"></span>
    </span>
</div>​

これが私のフィドルです:http: //jsfiddle.net/SN7Vn/1/

この動作と、ラジオボタンがブール値を更新しない理由(チェックボックスのように)を説明していただけますか?

4

2 に答える 2

5

チェックボックスとラジオボタンの動作は異なります。単一のオブザーバブルがchecked(配列ではなく)バインディングにバインドされている場合、それらは特に異なる動作をします。

チェックボックスの場合、チェックされているかどうかを示すブール値になります。単純。アレイの場合、はアレイにvalue追加/削除されます。

ただし、ラジオボタンの場合は、ラジオボタンに割り当てられた値になります。単一のオブザーバブルの場合、バインドされているものの値が値と等しいかどうかのみがチェックされていると見なされます。あなたの場合、あなたの値はにバインドされているので、値が対応するIDと等しいid場合にのみ応答します。chosen配列の場合、値を配列に追加/削除します。

chosen対応する属性のの値を変更するものは他にないため、同じままです

値がチェック状態にどのように影響するかを少し示すために、例を微調整しました。 更新されたフィドル

それはすべてドキュメントに詳しく説明されています。詳しく見てください。


チェックボックスの場合と同じように機能させたい場合は、正しく機能させるために少し作業が必要になります。私はこのコードを持っていますが、バインディングがどのように機能し、それらの順序の依存性が問題を引き起こす可能性があるため、少し壊れやすいと感じています。これを試してみることができますが、これがどれほど堅牢かはわかりません。

これが機能するためには、実際に選択されているラジオボタンに対する実際の変更を追跡するためのオブザーバブルが必要です。次に、そのオブザーバブルの変更をサブスクライブして、選択したオブザーバブルを更新できます。

ko.bindingHandlers.radiochecked = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        // the checked binding depends on the element having an initial value
        // we need to allow bindings that potentially set it to be applied first
        setTimeout(function () {
            var options = ko.utils.unwrapObservable(valueAccessor());
            if (options.checked()) {
                options.selected(element.value);
            }
            options.selected.subscribe(function (newValue) {
                options.checked(newValue === element.value);
            });
            ko.applyBindingsToNode(element, { checked: options.selected });
        }, 0);
    }
};

次に、それをラジオボタンにバインドします。

<input type="radio" data-bind="
    value: id,
    radiochecked: { 
        'checked': chosen,
        'selected': $root.attributeValues2.selected
    },
    attr: { name: 'test2' }" />

デモ

于 2012-11-16T23:52:37.850 に答える
1

これも役立つ場合があります。以下のバインディングは、ラジオボタンのグループを取り、それらの1つを変更すると、グループ内の残りすべての背後にあるobservableを特定の値(null、false、0、...)に設定します。

現状では、適切なラジオボタンを選択するには、observableの値がtrue/falseである必要があります。

ko.bindingHandlers.checkedRadio = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        $(element).change(function () {
            //Get all radio buttons int he group
            var group = $(element).attr('name');
            var radios = $('input[type="radio"][name="' + group + '"]').not($(element));

            //Reset all values for other radio buttons in this group
            $.each(radios, function (i, radio) {
                var $r = $(radio);
                if (!$r.prop('checked')) {
                    var data = ko.dataFor(radio);
                    data[allBindingsAccessor().checkedRadioProperty](allBindingsAccessor().checkedRadioValue);
                }
            });

            //Update bound data
            var value = valueAccessor();
            var checked = $(element).prop('checked');
            value(checked);
        });

        //Select radio button based on bound data
        var value = unwrap(valueAccessor());
        $(element).prop('checked', value);
    }
};

バインディングを使用するには、次のようになります。

<input type="radio" value="true" data-bind="name: 'option-group-' + attributeID() }, checkedRadio: chosen, checkedRadioProperty: 'chosen', checkedRadioValue: false" />
于 2012-11-19T18:58:57.247 に答える