我有一个带有observableArray项目的模型,这很好。 E.g。
var arr = ko.observableArray([{name: ko.observable('hello')}]);
我的问题是我想为这些不属于模型本身的项目设置单独的设置。在这种特殊情况下,我想跟踪所选记录。
如果我把这个项目放在模型中,那就太简单了。
ko.utils.arrayForEach(arr, function(item) {
item.selected = ko.observable(false);
});
但这会永久性地改变模型,并打破我想要添加新元素的其他地方。
所以我尝试的是制作一个可计算的数组,但是效果不好。
var selected = ko.computed(function () {
if (!arr()) return [];
return ko.utils.arrayMap(arr().list(), function () {
return ko.observable(false);
});
});
因为它会记住返回的项目,所以当arr更改时,它会以奇怪的方式破坏事物。
如何在保持同步的同时将这两件事分开?
答案 0 :(得分:1)
如果使用复选框,最好的方法是将checkedValue
绑定为对象,并将checked
绑定到根目录中的单独observableArray。然后使用复选框选择的每个项目都将位于根数组中。这与您提出的问题并不完全相同,但它是一个非常简单的解决方案,用于了解选择了哪个项目。
如果必须按照指定的方式执行,则可能必须复制数组(或使用原始数组的所有键创建引用数组),然后使用foreach
绑定列出对象和使用click
绑定将对象传递给将在引用数组中查找并设置所选/未选定属性的函数。
根据您的用户界面还有其他选项,因此可能会提供更多相关信息。
实施例
<div class="form-group" data-bind="visible: sites().length">
<label for="siteSelect" class="form-label col-sm-2"
Sites
</label>
<div id="siteSelect" class="col-sm-10" data-bind="foreach:sites">
<div class="col-md-4 col-sm-6"">
<input type="checkbox"
data-bind="checkedValue: SiteId, checked: $root.selectedSites, text: Name">
</input>
</div>
</div>
</div>
在我的veiwmodel中,我有:
var vm = {
sites: ko.observableArray([
{SiteId: 1, Name: 'Site 1'},
{SiteId: 2, Name: 'Site 2'},
{SiteId: 2, Name: 'Site 3'}
]),
selelctedSites: ko.observableArray([1]),
}
return vm;
这告诉knockout为数组'sites'中的每个项创建一个复选框,显示每个元素的Name属性,并为每个复选框设置SiteId值(bind:checkedValue)。 'selectedSites'数组将为每个选定的项目提供一个元素,该元素将是'checkedValue',或者在本例中为SiteId。如上所示,默认情况下将选中“站点1”的复选框。你也可以将checkedValue作为整个对象,如果它更好(给你一个选定对象的数组)。我认为,这通常比尝试协调两个数组更好。
如果这是您首选的界面,还有选择框(单选或多选)的选项。
希望这有帮助,如果您有更多问题请与我联系。
答案 1 :(得分:0)
//viewmodel
define(function () {
var ko = require('knockout'),
items = ko.observableArray([]),
selectedItems = ko.observableArray([]);
return {
items: items,
selectedItems: selectedItems
}
});
//view
<!-- ko foreach: items -->
<input type="checkbox" data-bind="checked: $parent.selectedItems, checkedValue: $data" />
<!-- /ko -->