【问题标题】:KnockoutJS radio buttons not changing like checkboxes doKnockoutJS 单选按钮不会像复选框那样改变
【发布时间】:2012-11-16 23:09:39
【问题描述】:

复选框和单选按钮的数据结构相同。选中复选框时,它们会返回正确的布尔值(“选择”变量)。

但是,当我检查单选按钮时,“选择”总是更改为“值”(整数)。

此外,单选按钮在开始时不会被“选中”,即使 '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/

您能否解释一下这种行为以及为什么单选按钮不更新布尔值(就像复选框一样)?

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    复选框和单选按钮的行为彼此不同。当单个 observable 绑定到 checked 绑定(而不是数组)时,它们的行为特别不同。

    对于复选框,它始终是一个布尔值,表示它是否被选中。简单的。如果是数组,value 将被添加/删除数组。

    但是对于单选按钮,它将是分配给单选按钮的值。对于单个 observable,它只会被认为已检查它绑定的值是否等于该值。在您的情况下,您的值绑定到 id 所以只有当 chosen 值等于相应的 id 时才会响应。对于数组,它将向数组中添加/删除值。

    由于没有其他东西改变相应属性的chosen 的值,所以它保持不变

    我调整了您的示例以演示该值如何影响选中状态。 Updated fiddle

    全部拼写成in the documentation,仔细看。


    如果您希望它的工作方式与复选框的工作方式类似,则需要做一些工作才能使其正确。由于绑定的工作方式以及它们的顺序依赖性如何导致问题,我有这段代码感觉有点脆弱。你可以试试这个,我只是不确定它有多强大。

    为此,您需要一个 observable 来跟踪实际选择的单选按钮的实际变化。然后,您可以订阅该 observable 的更改以更新您选择的 observable。

    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' }" />
    

    Demo

    【讨论】:

    • 感谢您的回答。我想要的只是“选择”为真/假是否选中“框” - 就像复选框一样。此外,如果我添加了一个下拉列表,我希望该值是真/假,无论该值是否在列表中被选中。这可能吗?
    • 获得这种行为是可能的,但需要一些工作。
    • 我有一个可能的解决方案来做你想做的事,但由于绑定的应用顺序和checked 绑定的工作方式未知,它看起来非常脆弱。正因为如此,我有点犹豫要不要分享这个。
    • 非常感谢,正是我想要的。 :)
    【解决方案2】:

    这也可能有所帮助。下面的绑定将采用一组单选按钮,在更改其中一个按钮时,将组中所有其他按钮后面的 observable 设置为特定值(null、false、0、...)

    就目前而言,它要求可观察对象的值是真/假,以便它选择正确的单选按钮。

    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-06-04
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 2017-01-07
      • 2015-12-09
      • 2013-08-07
      相关资源
      最近更新 更多