Roberto Serafin
Roberto Serafin

Reputation: 31

Knockout slow to bind huge amount of data

I'm using knockout to render a big quantity of data. (35000 record) I can't use lazyload request, passing by server, I have the data in the browser.

If I'm using observableArray in my ViewModel, the browser freezes for about 10 seconds, before showing the result of binding.

var vm = function () { 
      var ar = [];
      for (var i=0; i<35000; i++){ 
           ar.push(i);
      }
      this.SelectedElementsListData = ko.observableArray(ar);
}
ko.applyBindings(vm());

And with this HTML binding

<div data-bind="foreach:SelectedElementsListData" class="scrolling">
     <div data-bind="text:$data"></div>
</div>
<div data-bind="event: { click: fill }">
     CLICK HERE TO START
</div>

this is a prototype of the result needed

https://jsfiddle.net/RobertoSerafin/4axdwkfo/

My question is:

How can I make a generic customBinding, to make the foreach binding more sly, and apply rendering only to a partial list of ArrayItems, and using the div scrolling to render div only "onDemand", when the user scrolls the div.

Upvotes: 2

Views: 1452

Answers (2)

McCroskey
McCroskey

Reputation: 1161

Unless there is a particular requirement that you must use a custom knockout binding, it's probably easier to use a computed observable to give you a slice of the original array:

var vm = function () {
    var source = [];

    this.scroll = function() {
        var objDiv = document.getElementById("scroll");
        objDiv.scrollTop = objDiv.scrollHeight;        
    }

    this.visibleItems = ko.observable(50);

    this.more = function () {
        this.visibleItems(this.visibleItems() + 50);
        this.scroll();        
    }

    for (var i = 0; i < 50000; i++) {
        source.push(i);
    }

    this.visible = ko.computed(function() {
        return source.slice(0, this.visibleItems());            
    });        
}

ko.applyBindings(vm());
this.scroll();

Example on JSFiddle

You could, with a small modification, use this approach to implement a paged view of your data. That would be a lot nicer in terms of memory use, as you wouldn't keep adding items in the DOM as the user keeps clicking "Show More".

Upvotes: 1

Pharao2k
Pharao2k

Reputation: 695

You could try an in-place replace of the used binding handler and try https://github.com/brianmhunt/knockout-fast-foreach , but with that amount of items I don't think that'll be enough.

What you'll need is either paging or a virtualized list. The latter is that which you described in your last paragraph. With that as a search term, it should be easily enough to find a solution.

Upvotes: 1

Related Questions