Given a Knockout observableArray, to which items can be added and removed, how do I lay out the corresponding HTML elements with Isotope? Consider for example the following HTML, which declares a div #container that should be populated with child divs by Knockout:
<div id="container" data-bind="foreach: items, click: addItem">
<div class="item show" data-bind="text: text, click: $parent.removeItem, clickBubble: false"></div>
The accompanying JavaScript pre-populates the container with a couple of items, and lets the user click on items to delete them and click in the container to add new items (via Knockout):
function ItemModel(parent) {
var value, self = this,
found;
for (value = 0; value < parent.items().length; ++value) {
found = false;
for (i in parent.items()) {
var item = parent.items()[i];
if (item.value() == value) {
found = true;
break;
}
}
if (!found) {
break;
}
}
this.value = ko.observable(value);
this.text = ko.computed(function () {
return "Item " + self.value();
});
}
var ViewModel = function () {
var self = this;
self.items = ko.observableArray()
self.items.push(new ItemModel(self));
self.items.push(new ItemModel(self));
this.removeItem = function (item) {
self.items.remove(item);
return false;
};
this.addItem = function () {
self.items.push(new ItemModel(self));
};
};
ko.applyBindings(new ViewModel("Test"));
When coupled properly with Isotope, items should be laid out automatically by Isotope, including when items are removed, added and moved.
See this fiddle for a demo of the concept.
I have been able to integrate Knockout with Isotope by writing a special Knockout binding, called Knockout-Isotope. This facilitates integrating the two technologies greatly, and makes sure that Isotope stays synchronized with the Knockout view model. See the code below for an example of how to use this binding with a Knockout observableArray, or try the live fiddle.
Be aware though that this binding depends on a fork of Knockout in order to work.
Code
Demo fiddle.
HTML:
JavaScript: