我有一个Knockout组件,该模板打印两个嵌套的项目列表(我的界面中的复选框):第一个foreach循环遍历一些" parent" items,第二个(和嵌套的)列表遍历每个父项,如果找到子项,则打印子项。要求是,如果用户单击父项(即,在父复选框上),则会选中所有子项复选框。
在我的代码中,父母和子女复选框都会侦听首先设置为false的observable,然后在选择父级时将其设置为true - 结果:父亲的子项被选中。 我的问题是,这样,因为每个复选框都听同一个observable,我最终会选中所有选中的复选框,而不仅仅是我选择的父母+孩子,这就是我想要的。
我不确定如何以其他方式处理此问题,这是我的代码:
someClass
更新 JSON看起来像这样:
ko.components.register("types",{
viewModel: function(){
var self = this;
// Data
self.types = ko.observableArray();
self.isPChecked = ko.observable(false);
nut.structuredDocumentTypes()
.done(function (types) {
self.types(types);
});
// Behaviours
self.selectChildren = function(parent) {
self.isPChecked(true);
console.log(self.isPChecked(),parent);
}
},
template:
'<div id="doctypes" class="wfp-form wfpTreeList">\
<h2 class="hidden">Document Types</h2>\
<ul class="wfpList" data-bind="foreach: types">\
<!-- ko if: $index() > 0 -->\
<li class="root">\
<input\
type="checkbox"\
name="types"\
class="wfp-checkbox"\
data-select="multi"\
data-bind="\
checked: $component.isPChecked,\
event: { change: $component.selectChildren },\
value: $data.id">\
<input\
type="checkbox"\
name="acc"\
data-bind="\
attr: { class: \'lvl\' + $data.id, id: \'acc\' + $data.id }">\
<label\
data-bind="attr: { for: \'acc\' + $data.id }">\
<i class="ico-angle-down"></i>\
</label>\
<span data-bind="text: $data.label" class="root-title"></span>\
<ul data-bind="attr: { \'data-lvl\': \'lvl\' + $index(), id: \'lvl\' + $data.id }">\
<!-- ko foreach: $data.members -->\
<li>\
<label data-bind="attr: { for: \'dt-child-\' + $parent.id + \'-\' + $index() }">\
<input\
name="types"\
type="checkbox"\
data-bind="\
checked: $component.isPChecked,\
value: $data.id,\
attr: { id: \'dt-child-\' + $parent.id + \'-\' + $index() }">\
<span data-bind="text: $data.label"></span>\
</label>\
</li>\
<!-- /ko -->\
</ul>\
</li>\
<!-- /ko -->\
</ul>\
</div>'
});
谢谢大家。
答案 0 :(得分:1)
您应该通过扩展具有computed
属性的文档类型来略微准备您的数据,该属性取决于各个成员的状态。成员还应包含observable
属性以跟踪其已检查状态。
实现此类准备的最佳位置(我猜)是使用解码的JSON响应初始化types
属性的回调:
nut.structuredDocumentTypes()
.done(function (types) {
// we'll prepare types here
self.types(types);
});
因此,在评论中使用 Roy J (并由 user3297291 撰写)的小提琴方法,你会得到类似的结果:
nut.structuredDocumentTypes()
.done(function (types) {
types.forEach(function(type){
type.members.forEach(function(member){
member.isSelected = ko.observable(false);
});
type.isSelected = ko.computed({
read: function(){
return type.members.every(function(member){
return member.isSelected();
});
},
write: function(selected){
type.members.forEach(function(member){
member.isSelected(selected);
});
}
});
});
self.types(types); // insert prepared data
});
从我的小提琴中复制代码,我将组件分解为通常的视图模型,属性名称不同。请注意data-bind
属性的变化!