如何在淘汰赛中将模型与viewmodel分开?

时间:2014-12-05 06:35:27

标签: knockout.js model viewmodel durandal-2.0

我有一个带有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更改时,它会以奇怪的方式破坏事物。

如何在保持同步的同时将这两件事分开?

2 个答案:

答案 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 -->