Knockout.js and the fastest templating engine
I found out about this bug, http://bugs.jqueryui.com/ticket/6757 and someone answered it on a different issue that fixed it.
source to share
I created a binding specifically for fast table generation: https://github.com/mbest/knockout-table .
source to share
This answer is no longer accurate. Knockout 2.2 now supports reordering of elements via foreach binding.
The main problem with knockout observableArray
is that all operations that modify the array cause a complete reallocation of the elements below the binding foreach
. If this becomes a performance bottleneck, you can solve it by not moving the lines around but by copying their value.
The obvious way that returns everything foreach
on every change is as follows:
function Row(value) {
this.value = value;
}
var model = {
rows = ko.observableArray([new Row(1), new Row(2), new Row(3), new Row(4), new Row(5)])
}
function move(index, insertionIndex) {
var rows = models.rows();
// TODO Insert some clever code here
// - remove row from rows array
// - insert row at insertionIndex into rows array
rows.valueHasMutated();
}
Since this will redraw your entire table, this is probably not what you want. The best way would be to change the Row elements that support copying:
function Row(value) {
this.value = ko.observable(value);
}
Row.prototype.copyFrom(anotherRow) {
this.value(anotherRow().value());
}
Row.prototype.swap(anotherRow) {
var tmp = this.value();
this.value(anotherRow.value());
anotherRow.value(tmp);
}
var model = {
rows = ko.observableArray([new Row(1), new Row(2), new Row(3), new Row(4), new Row(5)])
}
function move(index, insertionIndex) {
var rows = models.rows();
var tmp = new Row();
tmp.copyFrom(rows[index]) // save the current row
if (index < insertionIndex) {
// move row down -> move other rows up
for (var i=index; i<insertionIndex; i++) {
rows[i].copyFrom(rows[i+1])
}
} else {
// move row up -> move other rows down
for (var i=index; i>insertionIndex; i--) {
rows[i].copyFrom(rows[i-1])
}
}
}
Note that you don't need to use anymore rows.valueHasMutated()
as you are not modifying the array, but modifying objects Row
. Therefore, the binding is foreach
not updated and you only overwrite the changed lines.
It would be great if knockout would provide a more powerful implementation of the binding handler observableArray
and foreach
that does not require re-modifying the entire template when changes are made. Until then, this is your best bet if you want to stick with the knockout.
source to share