Reputation: 757
I am kind of stucked with a ko.computed which I expect should be updated based on a add/remove action on an observableArray, but it does not, so I am probably missing something important here. So, I have an observable array, here it is:
vm.selTopics({
topics: [],
members: [],
children: []
});
Then I have a checkbox for a list of items in the main topics array, and I print the list applying a computed to each item. The computed should be updated anytime an item is added or removed in vm.selTopics() and the checkbox checked anytime the item is found in vm.selTopics(). Here is the code:
member.isSelected = ko.computed({
read: function(){
if(_.where(vm.selTopics().members, { id: member.tid, topicId: topic.tid }).length > 0){
return true;
}
},
write: function(val){
if(_.where(vm.selTopics().members, { id: member.tid, topicId: topic.tid }).length === 0) {
vm.selTopics().members.push({
id: member.tid,
label: member.label,
topicId: topic.tid
});
} else {
vm.selTopics().members.splice(_.findIndex(vm.selTopics().members, { id: member.tid, topicId: topic.tid }),1);
}
}
});
Then I have another computed which represents a checkbox that, if checked, checks the current member checkbox and those of its children. Here it the code for it:
member.isActive = ko.computed({
read: function(){
if(member.children.every(function(c){ return c.isSelected() }) && member.isSelected()){
member.isOn('isOn');
return true;
} else {
member.isOn('');
}
},
write: function(val){
if(member.children.every(function(c){ return c.isSelected() }) && member.isSelected()){
member.isSelected(false);
member.children.forEach(function(c){
c.isSelected(false);
});
} else {
member.isSelected(true);
member.children.forEach(function(c){
c.isSelected(true);
});
}
}
});
But when I click on this checkbox the member.isSelected computed does not get re-evaluated. (Just to be precise, vm.selTopics() was a uni-dimensional array before and everything worked fine...). Maybe I am missing some important part on how the triggers work. Thanks for your help.
UPDATE
Here is the HTML:
<input\
type="checkbox"
name="topics"
data-bind="
checked: isSelected,
value: tid,
">
<!-- Checkbox to select current member & its children -->
<label data-select="multi" data-bind="
css: isOn,
visible: $data.children.length,
event: { mouseover: $component.highlight, mouseout: $component.unlight },
">
<input type="checkbox"
data-bind="checked: isActive"
>
</label>
<!-- /ko -->
Upvotes: 0
Views: 355
Reputation: 16688
Storing an object in an observable doesn't make its properties observable. If you want to react to changes to the selTopics.members
array, then that must also be observable. Usually making an object observable isn't necessary unless that object is always updated atomically (such as data from an AJAX call).
vm.selTopics = {
topics: [],
members: ko.observableArray(),
children: []
};
Upvotes: 1