3

I need a faster template engine then the builtin knockout.js one. What is the fastest and how do you set it up? Any examples on the web? I have been thinking doT.js or handlebars. I want to wait for JsRender but the performance doesnt look up to par.

JstnPwll
  • 8,585
  • 2
  • 33
  • 56
Mike Flynn
  • 22,342
  • 54
  • 182
  • 341

3 Answers3

3

I created a binding specifically for fast table generation: https://github.com/mbest/knockout-table.

Michael Best
  • 16,623
  • 1
  • 37
  • 70
  • I will try this out and see if it works. I have a lot of nesting and anonymous binding going on so we will see. Are there any examples, simple and complex on jsfiddle? – Mike Flynn Jan 31 '13 at 20:33
  • There are examples in the README as well in the spec/tableBinding.js. I designed the binding to be pretty simple to use, but it's also fairly basic in its functionality. I'm sure, though, that you could extend the binding to suit your needs. – Michael Best Jan 31 '13 at 22:47
2

This answer is no longer accurate. Knockout 2.2 does now support reordering of elements via the foreach binding.

The main problem with knockout and the observableArray is that all operations that modify the array cause a complete rerender of the elements below the foreach binding. If this becomes a performance bottleneck you can solve this by not moving rows around but copying their value.

The obvious way which rerenders the entire foreach on every change is like the following:

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();
}

As this will redraw your entire table this is probably not what you want. A better way would be mutable 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 no longer have to use the rows.valueHasMutated() as you are not modifying the array but change the Row objects. Therefore the foreach binding does not update and you only rerender the changed rows.

It would be cool if knockout would provide a more powerful observableArray and foreach binding handler implementation which do not need to rerender the entire template on changes. Until then this is your best bet if you want to stick with Knockout.

bikeshedder
  • 7,337
  • 1
  • 23
  • 29
  • My rows are static, and I am already moving data inside each cell around. I can add rows though. – Mike Flynn Jan 31 '13 at 19:50
  • 2
    Knockout doesn't re-render the whole table if you add or remove items from the array. In fact, as of 2.2, if you just reorder the items, it will not re-render anything (http://blog.stevensanderson.com/2012/10/29/knockout-2-2-0-released/). – Michael Best Jan 31 '13 at 20:03
  • How did I miss this news? My answer just became obsolete. I'm sorry. – bikeshedder Jan 31 '13 at 21:12
1

I found out about this bug, http://bugs.jqueryui.com/ticket/6757, and had someone answer it for on another problem which fixed it.

Knockout.js and large dataset makes dropdown list slow also

Community
  • 1
  • 1
Mike Flynn
  • 22,342
  • 54
  • 182
  • 341