How to defer observable updating?
How can I defer the propagation of updates when document.history() changes until all changes are recorded?
by gene
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<div>Instructions:</div>
<div>Press the load button to load postings for each document. Click on the document link to see the associated postings. Look on the console to see that the Document.history.subscribe function was triggered once for each posting. I would like it to trigger only once for each load event.</div>
<button data-bind="click: load">load</button>
<div data-bind="foreach: documents">
<a class="document" href="#" data-bind="click: $parent.selectedDocument, text: title"></a>
</div>
<div data-bind="with: selectedDocument">
<div data-bind="foreach: history">
<div>
<span data-bind="text: rank"></span>
<span data-bind="text: snippet"></span>
</div>
<hr />
</div>
</div>
CSS
.document {
display: inline;
margin-right: 10px;
text-decoration: none;
}
body {
font-family: sans-serif;
font-size: 10pt;
}
JavaScript
Array.prototype.findById = function(id) {
for (var i=0; i<this.length; i++)
if (this[i].id == id)
return this[i];
return null;
}
function Document(id, title) {
var self = this;
this.id = id;
this.title = ko.observable(title);
this.history = ko.observableArray([]);
this.history.subscribe(function() {
console.log("history of doc " + self.id + " changed");
});
}
var docs = [
new Document(1, 'first doc'),
new Document(2, 'second doc'),
new Document(3, 'third doc')
];
function Posting(docid, rank, snippet) {
this.rank = ko.observable(rank);
this.snippet = ko.observable(snippet);
this.document = ko.observable(docs.findById(docid));
this.document().history.push(this);
}
function viewModel() {
var self = this;
this.documents = ko.observableArray(docs);
this.selectedDocument = ko.observable();
this.load = function() {
var posting1 = new Posting(1, 1, 'foo of doc1');
var posting2 = new Posting(2, 2, 'bar of doc2');
var posting3 = new Posting(1, 1, 'another foo of doc1');
var posting4 = new Posting(2, 2, 'another bar of doc2');
var posting5 = new Posting(3, 2, 'foo of doc3');
self.selectedDocument(self.documents()[0]);
}
}
ko.applyBindings(new viewModel());