New 1.3 features that can help with unobtrusive bindings
by rniemeyer
HTML
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-1.3pre.js"></script>
<div>
<h2 id="header"></h2>
<ul id="list" data-bind="foreach: items">
<li>
<span data-bind="text: name"></span>
<a class="remove" href="#">Remove</a>
</li>
</ul>
<a id="add" href="#" data-bind="click: addItem">Add Item</a>
</div>
CSS
a { font-size: .75em; }
JavaScript
/* There is now a hook that plugins can use to run code each time that ko.applyBindings is called
--note that applyBindings is called by the template engine as well */
ko.beforeApplyBindings = function(root) {
console.log("I am doing things each time that applyBindings is called", root);
};
var viewModel = {
items: ko.observableArray([
{ name: "one"},
{ name: "two"},
{ name: "three"}
]),
addItem: function() {
this.items.push({
name: "new"
});
},
removeItem: function(item) {
this.items.remove(item);
}
};
//There is now a way to apply bindings externally without using a data-bind attribute
ko.utils.domData.set(document.getElementById("header"), "bindings", function() { return { text: viewModel.items().length + " items" } });
ko.applyBindings(viewModel);
/* ko.dataFor gives you the overall data that was being bound against this element
ko.contextFor gives you an object that contains the data ($data) along with some other useful information ($parent, $parents, $root)
--useful for unobtrusive event handlers that need the context of an item/viewModel. Can use live/delegate to make sure that dynamically added items are still handled.
*/
$("#list").delegate(".remove", "click", function() {
viewModel.removeItem(ko.dataFor(this)); //"this" is the element and ko.dataFor(this) returns the item in this case.
});