Reputation: 588
Due to data being loaded via AJAX I need my data to be updated when data arrives.
On page load I collect projects in database. Then load data for Tasks and Tags depending on which project is selected (self.SelectedProject).
self.Projects = ko.observableArray();
self.Tasks = ko.observableArray();
self.Tags = ko.observableArray();
self.SelectedProject = ko.observable(); // Chosen Project-object...
For initialization I load data for the first Project:
self.SelectedProject(self.Projects()[0]); // Choose first returned Project...
Then I go on to populate my tag-helping arrays:
ko.computed(function () {
// must be ko.computed as else will not update when data arrives for Tags and Tasks (which are likely to be empty at load time)...
// Empty projectAvailableTags before refill...
self.SelectedProject().projectAvailableTags([]);
// First populate current project's "projectAvailableTags"-array with values...
for (var j = 0, jlen = self.Tags().length; j < jlen; j++) {
self.SelectedProject().projectAvailableTags().push(self.Tags()[j].TagName());
}
for (var i = 0, ilen = self.Tasks().length; i < ilen; i++) {
//---- Populate each TaskTag-array with Tags...
for (var j = 0, jlen = self.Tags().length; j < jlen; j++) {
if (self.Tags()[j].TagTaskId() === self.Tasks()[i].TaskId) {
self.Task()[i].TaskTags.push(self.Tags()[j]);
// Populate the different tag-Arrays...
var tagtype = self.Tags()[j].TagType;
switch (tagtype()) {
case 0: self.Tasks()[i].Location().push(self.Tags()[j].TagName()); break;
case 1: self.Tasks()[i].Manager().push(self.Tags()[j].TagName()); break;
case 2: self.Tasks()[i].Employee().push(self.Tags()[j].TagName()); break;
}
}
}
};
});
This probably look strange and maybe I am doing it unnecessarily complicated. I use http://aehlke.github.com/tag-it/ as tag manager and it needs an array with TagNames only. Thus I haven´t figured out how to use the Tags()-array directly although I´d like that.
Tasks are presented in an accordion, and I want the Task-tags to be applied in the content panel, while I use my Project-tags as the tagSource for autocomplete-functionality...
But I cannot figure out why my tags are applied 2 times with the ko.computed while they aren´t applied unless I reselect the project without it.
Upvotes: 0
Views: 1462
Reputation: 702
I think you're kind of missing the point of computed observables. The only real distinction between computed observables and a regular function is that you can bind to a computed observable and rely on it to auto-update any time one of its components changes.
The example in the knockout documentation for computed observables uses First/Last name, which is a good example.
Based on this, it's really not a good idea to update the dependency of a computed within that computed itself. In earlier version of knockout this would have actually create an infinite circular reference.
I assume the computed is running twice because Tags and Tasks are both receiving new data, which is triggering an update (but only one update because of the safeguards built into knockout).
A better option would be to subscribe to SelectedProject. Then every time that observable changes you can re-rack all your arrays.
self.SelectedProject.subscribe(function(newValue) {
<load your arrays here>
});
Upvotes: 1