2012-11-16 76 views
3

我有相同的复选框和单选按钮的数据结构。当检查复选框时,它们会返回正确的布尔值('selected'变量)。KnockoutJS单选按钮不会像复选框一样变化

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

而且单选按钮没有得到 “选中” 在开始的时候,即使 '选择' ==真

的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/

你能解释这种行为,为什么单选按钮不更新布尔(就像复选框一样)?

回答

5

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

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

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

由于没有别的改变chosen的相应属性的值,它仍然是相同的

我优化了你的例子来说明一点的价值是如何影响的选中状态。 Updated fiddle

这一切都拼写出来in the documentation,仔细看看它。


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

为了达到这个目的,您需要一个可观察值来跟踪实际选中单选按钮的实际更改。然后,您可以订阅该可观察项的更改以更新您选择的可观察项。

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

+0

谢谢您的回答。我想要的就是“选择”是否为“复选框”,是正确/错误 - 就像复选框一样。另外,如果我添加了一个下拉列表,我希望该值是true/false,无论该值是否在列表中被选中。这可能吗? – Gaui

+0

有可能获得该行为,但需要一些工作。 –

+0

我有一个可能的解决方案来做你想做的事情,但由于应用绑定的未知顺序以及'checked'绑定的工作方式,它似乎非常脆弱。因为这个,我有点犹豫分享这个。 –

1

这也可能有帮助。下面的绑定将采用一组单选按钮,在更改其中一个单选按钮时,将组中其余部分的观察值设置为特定值(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" />