Sencha Inc. | HTML5 Apps

Blog

Infinite Grid Scrolling in Ext JS 4

May 10, 2011 | Ed Spencer

Infinite Grid Scrolling in Ext JS 4 Grids are an excellent way of showing large amounts of tabular data in a web browser. Essentially a supercharged HTML table, the Ext JS 4 GridPanel makes it easy to fetch, sort and filter potentially unlimited amounts of data. In version 4, we revisited the fundamental architecture of the grid, challenging previous assumptions and unlocking some exciting new features and functionality. Today, we’re going to take a quick look at how a few of these combine to add power and flexibility to your applications.

One of the most exciting aspects of the new grid system is its ability to handle unlimited amounts of data without paging. In previous versions, all of the data was rendered at once, which put a limit on the number of rows that could be present before the browser ran out of memory. The alternative was to use paging, only showing a single page of data at a time, but this is often not ideal for the user.

To enable your applications to present infinite data sets without paging, we developed a brand new virtualized scrolling system for Ext JS 4. The new system only renders a handful of rows at a time, seamlessly swapping out data as you scroll. Unlike other infinite scrolling solutions, we are not simply recycling existing rows and replacing their values — each row is still being rendered just like normal. This delivers two enormous benefits — the ability to have variable row heights, and the ability to expand and collapse rows at any time.

Creating an Infinite Grid

Let’s jump straight in and create our infinite scrolling grid. Of course, the first thing we need is a data set, so for this example we’re going to use the Ext JS forum posts. We’ll start by setting up a Model that represents a single forum thread:

 
Ext.define('Thread', {
  extend: 'Ext.data.Model',
 
  idProperty: 'threadid',
  fields: [
    'threadid', 'title', 'forumtitle', 'forumid', 'author', 'lastposter', 'excerpt', 'replycount',
    {name: 'lastpost', type: 'date', dateFormat: 'timestamp'}
  ]
});
 

Most of the fields can simply be specified by name and will be given an automatic type. We specified lastpost as a date with a dateFormat configuration, so the Thread model knows how to decode the date from the server response. Now that we have a Thread model defined, we can use it with a Store to retrieve the forum data:

 
var store = Ext.create('Ext.data.Store', {
  model: 'Thread',
  pageSize: 200,
  autoLoad: true,
 
  remoteSort: true,
  sorters: {
    property: 'lastpost',
    direction: 'DESC'
  },
 
  proxy: {
    type: 'scripttag',
    url: 'http://www.sencha.com/forum/remote_topics/index.php',
    extraParams: {
      total: 50000
    },
    reader: {
      type: 'json',
      root: 'topics',
      totalProperty: 'totalCount'
    },
    simpleSortMode: true
  }
});
 

We’re exercising several of the Store configurations here. We created a fairly customized ScriptTagProxy which will load data using JSON-P, defined a JSON Reader to decode the response, and passed an extra parameter that tells the server to send back up to 50,000 results. We also defined a pageSize configuration that asks the server to return data in chunks of 200.

As the user scrolls through the list, our infinite scrolling grid will use these configurations to pull down data in blocks of 200. This is done based on how close the user is to the edge of the currently loaded data set — for example, if there are 200 records loaded currently, the grid will load the next block when the user scrolls down to about record 150.

Now that we have the Model and the Store, we can finish the job by creating the grid itself. This is the same as any other grid — all we have to do is specify that we’re using a paginggridscroller and we’re done:

 
Ext.create('Ext.grid.GridPanel', {
  width: 700,
  height: 500,
  renderTo: Ext.getBody(),
  store: store,
 
  verticalScroller: {
    xtype: 'paginggridscroller'
  },
 
  columns: [
    {
      xtype: 'rownumberer',
      width: 40,
      sortable: false
    },
    {
      text: "Topic",
      dataIndex: 'title',
      flex: 1
    },
    {
      text: "Replies",
      dataIndex: 'replycount',
      align: 'center',
      width: 70
    },
    {
      text: "Last Post",
      dataIndex: 'lastpost',
      width: 130,
      renderer: Ext.util.Format.dateRenderer('n/j/Y g:i A')
    }
  ]
});
 

Loading the page now shows us something like this:

Infinite Grid Scrolling in Ext JS 4

This looks just like a normal grid, but once you start scrolling you’ll notice that it just keeps going without paging. Infinite grids are an awesome new technology, brand new to Ext JS in version 4. They often provide a better experience for your users, who no longer have to worry about which page they happen to be on; and infinite grids provide a highly scalable solution for manipulating enterprise-scale data sets.

There are 30 responses. Add yours.

Vladislav Holovko

3 years ago

Finally, you did it! )

k0smita

3 years ago

Can one do HORIZONTAL infinite scrolling with this? For thousands of columns?

asam d besam

3 years ago

Flex still rules

Roman Savko

3 years ago

Great example, thanks!
What about multiple (nested) grouping with infinite grid?

Arsen

3 years ago

Maybe small example - with php file, which gives this data, will be more helpfull, than this “we deed”.
Am wriitng this, cause i know (from few large projects i made this year) how
complex is to implement of every new future in Ext.

Also, very interesting is how fast is it, when reordering, moving to last record, tro first, how is possible to show current percentage ... ie all- that clients want’s.

Krishna Annamraj

3 years ago

This is cool and will be good for only some scenarios..I believe we can’t completely replace paging as it is still user friendly and you will come to know when you use it what I meant to say…..Krishna

Wallysson Nunes

3 years ago

Well, i do not think pagin it’s frielndly user, you can see that 90% of the user wich uses Google do not pass from the third page…

Infinite Grid, im my opinion is the best choice in any case.

Predator

3 years ago

I told you to do this a million years ago. Finally you did it. Thank god!

Victor

3 years ago

Good job! I really like it.

AwesomeBob

3 years ago

K0smita, what purpose would that many columns serve?

Leather

3 years ago

Sounds good but why not post an actual example along with it? I think most readers would agree it’s much easier to get an undertsanding if we can actually see it working and examine the traffic in Firebug etc.

Eugene

3 years ago

Great example! Except.. it doesn’t work. First, the only way to scroll the grid is by pulling the scroll thumb. Second, it crashes when it tries to load the next page with the following error:
“Uncaught TypeError: Cannot call method ‘getByKey’ of undefined” in ext-all-debug.js:44345

necco

3 years ago

What about infinite grid scrolling with memory proxy? I want to work with local data kept all in memory but filtering and live searching do not work for the entire set of data. I think it works only with the buffered data.

Is it possible to have infinite grid scrolling with local data (proxy : ‘memory’) with live searching and filtering for the entire data set?

James Goddard

3 years ago

Ed, there is currently an open bug on this.  If you try to use an infinite scroll on a data store that contains no records it gives an error (Start (0) was greater than end (-1)).

James Lorenzen

3 years ago

This looks great.
How does sorting behave with infinite scrolling if the store hasn’t loaded in all the data? Your example, gives the appearance that the client is requesting 200 records which indicates the server needs to be able to support that feature. Is that correct?

Olof

3 years ago

Is there an eta for infinite scrolling support for selection? I.E. selecting rows on different “pages”.

Olof

3 years ago

Is there an eta for infinite scrolling support for selection? I.E. selecting rows on different “pages”.

Thanks

Olof

gorkunov

3 years ago

Buffered grid and infinite scrolling contain many issues: work with empty store, reloading grid, saving selection, applying remote sorters and filters etc. So currently this behavior works correctly only on example page :(.

Fredric Berling

3 years ago

In those (not so often) cases where you cant convince someone, that if you get a grid with more than 500 rows, you are doing it wrong. A result showing 500 results just shows that you searched wrong (if your domain isnt google.com).
Thanks for making this possible for us Sencha. Now we have even more alternatives.

Marcus Boos

3 years ago

Thank you for this tutorial.
I have several grids which might benefit from that new ext4 feature.

Gevik

3 years ago

This is a very welcome addition to the Grid. For Ext3 there was the LiveGrid alternative IIRC. What is really interesting about this is the “verticalScroller” functionality which opens possibilities for more features.

Michael V

3 years ago

What i don’t like about this approach is, that i have a fixed size scroll bar. In your example, you declare a fixed total of 50000 for proxy, which seems be used to calculate the height for the scroll bar. This value isn’t adjusted, later. So this isn’t a real infinite solution, plus i could easily scroll beyond the end of my dataset, if there are less than 50000 rows. Is there a more dynamic way of doing it? E.g. the scrollbar should adjust after each remote request.

John does it

3 years ago

Having such grid will probably make you realize how useless this thing is. Will the user be able to browse 10 million records or find anything he’s looking for? Nope. User must be able to reduce the number of rows to several hundred at most to be able to do anything useful with them.

Sebastien Tardif

3 years ago

Test shown that Infinite Grid Scrolling is unable to handle the simpler grouping in conjunction with column locking. In other words, features are exclusive.

Aaron Bartell

3 years ago

I might be missing something, but this seems to be purporting some really bad programming practices.  If you have 10,000 records returned in a result set, it took many CPU cycles and bandwidth to make that happen (i.e. deliver JSON/XML over the wire from server to browser).  Programming things like this will inevitably cause people to need more servers vs. if they had just used the paging techniques and only returned as many records as was reasonable for the particular business case.

Just my $.02,
AaronBartell.com

Toh

3 years ago

I have tried the example, if you scroll fast by dragging cursor, many requests are done to the server. Why not cancelled old requests and keep only the last one when the cursor is released ?
If you watch the request parameters, a page number is ask to the server. When you move up and down requests are done.
For example you ask for data starting at page 150, then you go down you ask data starting at page 200. If you go up a request is done but it not ask for the page 150, it ask the page 151 !
It would be better to ask for the page 150, this request may be catched.

We can read it is “great”, “amazing”, “infinite” ....
But for me it is not completed yet.

Sabine

3 years ago

Any chance of an example with remote live search?

Ram

3 years ago

1. Infinite grid should support infinite selection also. For eg select row1, scroll down and select 350. The internal row selection model must provide this data.
2. Scroll bar height has to be adjusted based on the total count returned from proxy
3. Scrolling issues needs to be fixed
http://www.sencha.com/forum/showthread.php?132642-Buffered-Store-with-infinite-grid-scrolling-issues

Pankaj

3 years ago

How this will work in case when the user wants to sort (at any point of time) on any column and want to see the sorted (or filtered) resultset taking into account the whole bunch of data with virtual pagination still in place?

LoreZyra

3 years ago

I’m with Olof. Why doesn’t infinite grid support selection? Is there an ETA to have it support the rowSelectionModel?

Comments are Gravatar enabled. Your email address will not be shown.

Commenting is not available in this channel entry.