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?
activeproperty on the array elements an observable and simply toggle that. This way, you would not need to add and remove array elements at all. - janfoeh