Reputation: 3143
Using Knockout via Durandal (v. 1.2) a Knockout Observable doesn't update the binding after being updated as the result of an AJAX call, except the first time.
ViewModel:
define(["require", "exports"], function(require, exports) {
var About = (function () {
function About() {
var _this = this;
this.Code = ko.observable("Initial Content");
$.get("MyXml.xml", function (data) {
return _this.DataLoaded(data);
}, "text");
}
About.prototype.DataLoaded = function (data) {
this.Code(data.toString());
};
return About;
})();
return About;
});
View:
<div>
<h2>About</h2>
<p data-bind="text: Code"></p>
</div>
The viewmodel is being bound to the view via Durandals composer, but I've run into the same problem with vanilla Knockout. The content of the file is correctly displayed the first time the view is composed, but when the view is composed again after that the binding is not updated after the initial value. The file is loaded, and the code to update the observable is called, no errors thrown. Previously I've solved the problem simply by delaying the update with a setInterval. That combined with the fact that it works the first time, for me suggest that it is a race condition bug. But I can't figure out what the problem would be.
Is there any time period where you shouldn't update an observable? And is there a good pattern to avoid this?
Edit
For now I'm using the viewAttached method (Durandal) to know when it's safe to update, but I would still like to know the root cause, and possible any better solutions.
Upvotes: 2
Views: 341
Reputation: 2603
Initializing stuff should be safe there. I also use the activate hook and return a promise in there. Not sure which one is the preferred event.
The root problem is probably because of the lack of a promise from your Ajax call. Try to at least use $.Ajax
with async: false
.
Upvotes: 1