我有一个可观察的服务数组,可能由某个公司(即Sales,Service,Consulting)提供。这些服务中的每一项都可由公司在美国零个或多个州执行,并且每个州都有一个可选的认证号码。因此,该服务具有可观察的位置阵列,位置是状态和证书编号的组合。Knockout:与可观察数组和复选框的复杂绑定
function Service(name) {
var self = this;
self.Name = ko.observable(name);
self.Locations = ko.observableArray();
}
function Location(state) {
var self = this;
self.State = ko.observable(state);
self.CertNum = ko.observable();
}
在用户界面中,我想显示美国所有州的单一列表。用户会勾选公司运营所在州的每个州旁边的复选框,从而制作州的“主列表”。这个主列表反过来驱动出现在每个可能的服务下的选择。
例如,用户在主列表中勾选“阿拉巴马州”和“亚利桑那州”。 UI然后为每个服务呈现单独的位置作为复选框和文本框的组合。这里的主视图模型:
function viewModel() {
var self = this;
self.AllStates = [
{ name: "Alabama", abbrev: "AL" },
{ name: "Alaska", abbrev: "AK" },
{ name: "Arizona", abbrev: "AZ" },
{ name: "Arkansas", abbrev: "AR" }
];
self.BusinessStates = ko.observableArray();
self.AllSelectedStates = ko.computed(function() {
return ko.utils.arrayFilter(self.AllStates, function(item) {
return self.BusinessStates.indexOf(item.abbrev) >= 0;
});
});
self.Services = ko.observableArray([
new Service("Sales"),
new Service("Service"),
new Service("Consulting")
]);
}
一个简单的观点看起来像:
<h2>Master List</h2>
<ul data-bind="foreach: AllStates">
<li>
<label><input type="checkbox" data-bind="value: abbrev, checked: $root.BusinessStates"/> <span data-bind="text: name"></span></label></li>
</ul>
<h2>Services</h2>
<div class="service" data-bind="foreach: Services">
<h3 data-bind="text: Name"></h3>
<ul data-bind="foreach: $root.AllSelectedStates">
<li>
<label>
<input type="checkbox" data-bind="value: abbrev, checked: $parent.Locations" />
<span data-bind="text: name"></span>
</label>
<input type="text" placeholder="Cert. Number" data-bind="value: ??" />
</li>
</ul>
</div>
至少查看得到我的状态进入了服务的位置排列,但我不知道该怎么绑定CertNum属性。
假设用户在主列表中选择了阿拉巴马州和亚利桑那州。现在,对于“销售”服务,用户勾选“亚利桑那州”并输入认证号码“98765”。在“咨询”服务下,用户勾选“阿拉巴马州”并且不输入证书编号。理想情况下,我想生成的JSON片段看起来像:
"Services": [
{
"Name": "Sales",
"Locations": [
{
"State": { "name": "Arizona", "abbrev": "AZ" },
"CertNum": "98765"
}
]
},
{
"Name": "Service",
"Locations": []
},
{
"Name": "Consulting",
"Locations": [
{
"State": { "name": "Alabama", "abbrev": "AL" },
"CertNum": null
}
]
}
]
我可以渲染并结合美国各州的“主列表”。我可以迭代服务并呈现一个UI,为每个可用服务位置(即状态复选框,证书编号文本框)提供控件。我无法绑定服务位置控件以控制相应位置数组中位置的成员资格,并同时影响证书编号的值。
我所做的最接近的尝试是非常复杂和黑客,我使用knockout-postBox plugin将viewModel.AllSelectedStates属性链接到每个服务模型上的类似属性,然后将新位置推送到每个Service.Locations中阵列。它几乎的作品,除非它擦除了对服务的更改,只要主列表中选中或取消选中状态。此外,我必须将每个可用位置都推送到每个服务的位置数组中,并依靠该位置上的IsSelected布尔标志来确定它是否已被选中(我宁愿将只是数组中被选中的位置)。
你可以看到在此的jsfiddle尝试:http://jsfiddle.net/cbono/PU6Sq/23/
关于它的好处是,它表明了用户界面应该如何表现。但是我认为没有postBox插件这是可能的,我只是没有找到解决问题的正确方法。我已经花了好几天的时间来解决这个问题,并且不能提出一个100%的解决方案。
谢谢,马库斯。我没有完全使用你的解决方案,但你帮助我走上了正确的道路。从一个模型向另一个模型发送可观察的项目数组是我没有想到的。但是,我并没有发送整个状态数组,而是创建了一个依赖的可观察值,该可观察值被过滤到所选的状态并使用它。像魅力一样工作! – CBono