Reputation: 14620
I've read through a number of questions and answers that have mentioned a number of reasons for observableArrays not updating the UI. I've worked through some of these and at first glance it appeared I was not working in the observable scope, so changes to the underlying array where not being updated in the observable as would be expected.
I started using the replace method on observableArray
to try and solve the problem.
var self = this;
this.rightMenu = ko.observableArray();
this.activate = function(data, event) {
var index = self.rightMenu.indexOf(data),
active = _.findWhere(self.rightMenu(), {active : true}),
toActivate = self.rightMenu()[index];
data.active = true;
self.rightMenu.replace(toActivate, data);
self.rightMenu.replace(active, $.extend(active, { active : false}));
};
Essentially I am just updating the active property on the objects. I was lead to believe that using the observable methods would trigger knockouts DOM listeners and update those elements. This is not happening in the above scenario.
If I console.log self.rightMenu()
after the replaces, I see exactly what I should. Active classes in the DOM however are not updated.
If I do this:
self.rightMenu.push({name : 'test', href : 'test', active : true});
The DOM does update with the new value I push to it.
The DOM node this VM is bound to looks like this:
<ul class="sidebar right" data-bind="foreach: rightMenu">
<li data-bind="css: $data.active ? 'active' : ''">
<a data-bind="click:$root.activate, text:$data.name, attr { href : $data.href}"></a>
</li>
</ul>
Can anyone give me a pointer as to how I could fix this?
Upvotes: 0
Views: 3152
Reputation: 16368
I'm not a knockout
expert but I could solve your problem by copying your data object into a new object.
self.activate = function(data, event) {
var index = self.rightMenu.indexOf(data);
var obj = {
active: true,
name: data.name,
href: data.href
}
self.rightMenu.replace(self.rightMenu()[index], obj);
}
Upvotes: 2