2013-02-11 65 views
2

我正尝试使用Knockout.js创建复选框的列表。该列表本身来自数据绑定源,以及列表中的哪些项目被选中。我有这个模型看起来是这样的:使用Knockout.js创建数据绑定复选框时未选中任何内容

var ViewModel = function() 
{ 
    this.areas = [{AreaId: 1, Name: 'Test 1'}, {AreaId: 2, Name: 'Test 2'}, {AreaId: 3, Name: 'Test 3'}]; 
    this.AreasImpacted = ko.observableArray([1, 2]); 
}; 

现在,我想创建的复选框列表与标签测试1测试2测试3。我想要测试1测试2检查。我的HTML看起来像这样:

<span class="areas" data-bind="foreach: areas"> 
    <label><input type="checkbox" data-bind="value: AreaId, checked: $parent.AreasImpacted" /><span data-bind="text: Name"></span></label> 
</span> 

绘制每个复选框用正确的名字,我可以验证每个复选框的value属性被设置正确,但是没有得到确认!我也尝试将this.AreasImpacted设置为2。当我这样做时,所有3个复选框都会被检查!

完全困惑!

更新:

如果我改变模式:

this.AreasImpacted = ko.observableArray(['1', '2']); 

然后,事情按预期工作。

如果我不得不猜测,我会说for-each绑定正在将每个值转换为一个字符串。我很好奇,如果这是设计,或Knockout.js错误。我期望输入的值是数字,因为这是我所约束的。提起

错误:

由于上述代码并不如documented工作,我已经提交GitHub上一个bug

回答

2

你需要改变的事情了一下,检查是否正在渲染区域的AreaId包含在AreasImpacted数组中:

data-bind="value: AreaId, checked: $parent.AreasImpacted.indexOf(AreaId) >= 0" 

了工作演示见this fiddle

注:使用该技术,选中或取消选中的绑定复选框将更新数据源之一。

或者,可以使字符串数组列表,像这样:

this.AreasImpacted = ko.observableArray(['1', '2']); 

的演示中看到this fiddle


正如评论指出的那样,KnockoutJS documentation似乎表明,OP的原始语法应该工作。您甚至可以通过将数组中的项目设置为字符串(demo)来实现该目标。

KnockoutJS源可以告诉我们为什么会发生这种情况。看看checked.js default binding看到的代码中的相关位将决定是否检查输入与否:

element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0; 

在这种情况下:

  • value是区域的ID(数字,在数组的OP的原代码)
  • element<input .../>复选框的HtmlElement

这样,element.value将始终是字符串类型,这就是为什么仅当数组中的项目也是字符串时才会检查复选框。

在KnockoutJS中是否这是一个错误,或者只是一些意想不到的逻辑行为:我不确定。

+0

从[Knockout Docs](http://knockoutjs.com/documentation/checked-binding.html):*如果您的参数解析为数组,则会给予特别的考虑。在这种情况下,如果值匹配数组中的项,KO将设置要检查的元素,如果数组不包含,则取消选中。* - 含义,因为'AreasImpacted'是一个数组,所以应该检查if该项目存在于数组中。为什么它不像记录的那样工作? – 2013-02-11 23:59:03

+0

嗯,你说得对。不要问我“为什么”(但),但[它在使用数组中的字符串时有所帮助](http://jsfiddle.net/jeroenheijmans/TXhtA/):O – Jeroen 2013-02-12 00:12:18

+0

@MikeChristensen更新了我的答案,if我没有弄错,我发现为什么KnockoutJS会这样做。 – Jeroen 2013-02-12 01:00:40