Adding items to a jqui sortable via Knockout bindings
Get jQuery UI's sortable to recognize elements added through Knockout's foreach template binding. (Portions borrowed from http://jsfiddle.net/rniemeyer/Myue3/)
by medmunds
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/jquery.tmpl.js"></script>
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-1.1.2.debug.js"></script>
<div data-bind="customView: {}">
<p>These are sortable:</p>
<ul class="sortableList" data-bind="template: { name: 'itemsTmpl', foreach: items, afterRender: afterRender }"></ul>
</div>
<button data-bind="click: addOneItem">Add One Item</button>
<button data-bind="click: addThreeItems">Add Three Items</button>
<button data-bind="click: clearLog">Clear Log</button>
<script type="text/x-jquery-template" id="itemsTmpl">
<li>
<span data-bind="text: name"></span>
<a data-bind="click: function() { viewModel.removeItem($data) }">Remove</a>
</li>
</script>
<div id="console">
<p>Console:</p>
</div>
CSS
ul {
margin: 1em 0;
border: 1px solid #cccccc;
background: #eeeeee;
}
li {
margin: 0.2em;
padding: 0.2em 0.4em;
border: 1px solid #dddd00;
background: #ffffdd;
}
li > a {
float: right;
color: #0000ff;
text-decoration: underline;
}
#console {
font: 8pt monospace;
margin-top: 2em;
padding: 0.2em;
background: #eeeeff;
}
JavaScript
var id = 1;
var renderCount = 0;
var viewModel = {
items: ko.observableArray([
{ name: 'Item '+id, id: id++ },
{ name: 'Item '+id, id: id++ },
{ name: 'Item '+id, id: id++ }
]),
afterRender: function(renderedNodes, data) {
log("afterRender " + (++renderCount)
+ " rendering " + renderedNodes.length + " nodes");
},
addOneItem: function() {
this.items.push(
{ name: 'Item '+id, id: id++ }
);
},
addThreeItems: function() {
this.items.splice(this.items().length, 0,
{ name: 'Item '+id, id: id++ },
{ name: 'Item '+id, id: id++ },
{ name: 'Item '+id, id: id++ }
);
},
removeItem: function(itemToRemove) {
this.items.remove(itemToRemove);
}
};
///////////////////////////
// jQuery.ui.sortable simple ko binding
ko.bindingHandlers.customView = {
init: function(element) {
log("customView binding init");
$(".sortableList", element).sortable()
.disableSelection();
},
update: function(element) {
log("sortable binding update");
}
};
///////////////////////////
ko.applyBindings(viewModel);
function log(message) {
$("#console").append(document.createTextNode(message)).append("<br/>");
}
function clearLog() {
$("#console").empty();
}