3

I have an observable array ListingData which I am using to bind data in a HTML table using knockout like this:

<tbody data-bind="foreach: ListingData">
    <tr>
        <!-- ko foreach: $parent.OrderedColumns -->
        <td>
            <span data-bind="text: $parent[$data]"></span>
        </td>
        <!-- /ko -->
    </tr>
</tbody>

OrderedColumns is a simple array containing the column names which I am using to bind the grid data dynamically. Since the user can configure the number rows and columns which will be displayed in the grid, I am using the above syntax.

The user can configure upto 500 rows and 50 columns maximum. I am getting the 50 x 500 data in a single ajax request and storing it into the ListingData observable array. The problem I am facing is that when I set the value for ListingData observable array, KO will try to generate the markup of all 50 columns and 500 rows given in the foreach binding at once which is causing the browser to hang and it gives the Stop script / Continue script message. I tested with 50 columns and 500 rows, it is taking about 6-7 secs to bind the data and during this period the browser is getting hanged.

My question is, is there anyway to generate markup as the user scrolls through the tbody of html table using knockout? For example in my request I will get all 50 columns and 500 rows and store it into an observable array and on page load, only 10 or 20 records will be visible to the user. As the user scrolls through the html table, we need to generate the markup of remaining records using the data already present in the observable array, rather than making an ajax call to get the remaining records each time the user scrolls down. After scrolling through all 500 records, if the user clicks on next page, this time we will send an ajax request get the next 500 records and show only 10 or 20 records and generate markup as user scrolls down in the 2nd page.

Is there any way to achieve this in Knockout like using knockout templates or on demand loading etc?

seadrag0n
  • 848
  • 1
  • 16
  • 40
  • KoGrid has virtual scrolling, have you tried it? – Anders Jun 30 '14 at 16:55
  • Here is a fiddle I did showing their Virtual Scrolling, its not superfast but maybe fast enough. Its 500x50 http://jsfiddle.net/MBhAS/ – Anders Jun 30 '14 at 17:10
  • 3
    I'd rethink your UI. Does a user really need to view 25,000 cells on a single page? Unlikely. It's not even humanly reasonable that they could make use of all of that data at once. – xdumaine Jun 30 '14 at 19:31
  • @Anders any other alternative to KoGrid which I can use in my existing syntax? something like this: http://stackoverflow.com/questions/17748448/knockout-virtual-scrolling-binding/20644787#20644787 – seadrag0n Jul 01 '14 at 05:25
  • @xdumaine this is a requirement by the client and we have deliver it no matter what.... – seadrag0n Jul 01 '14 at 05:26
  • What's wrong with the answer you just linked to? – xdumaine Jul 01 '14 at 09:50
  • @xdumaine I have implemented the answer in the link which I gave in my previous comment and it is working good. Should I post that as an answer here or wait for some other answers? – seadrag0n Jul 01 '14 at 10:10

1 Answers1

1

If your problem is rendering a lot of elements, you can use client side pagination adding the following elements:

  • CurrentPageRows (Computed Observable)
  • StartIndex Observable (index of the first row of the page)
  • PageSize Observable

CurrentPageRows will return the current page according to the current StartIndex and PageSize.

You will also have to add some buttons/links to go to the next/previous page that will basically set StartIndex to the calculated index of the page you want to go :

StartIndex(math.floor ( PageNumber / PageSize ) + 1 )

The key is the computed observable that will only render a subset of all the records.

Hugo Zapata
  • 4,314
  • 5
  • 29
  • 32