Dyna-grid

From Jsorm

Jump to: navigation, search

Contents

Overview

dyna-grid is an extension to the excellent ExtJS library by Jack Slocum. It answers one real shortcoming of ExtJS grids, which are used to present data: the grid does not handle very large datasets particularly well. If you want to use a large data set, you have 2 choices:

  • Load it all at once. This can lead to abysmal performance in most browsers, and large network traffic before it is loaded.
  • Use paging. This works quite well, except that, for many user interfaces, paging is unacceptable.

dyna-grid extends ExtJS to resolve this issue.

Additionally, dyna-grid has a PagingMemoryProxy that allows in-memory data stores (as opposed to server-side) to understand and replicate paging semantics.

It is strongly recommended that you understand how to use ExtJS before using dyna-grid.

Release information is available.

When To Use It

You should use dyna-grid when you:

  • need a single grid view for large sets of data without using paging
  • need to test the behaviour of a Store and/or Grid in a paging situation without relying on the server

Usage

dyna-grid adds these features by creating three new classes:

  • JSORM.ext.DynaGrid, aliased to Ext.ux.grid.DynaGrid, which extends Ext.grid.GridPanel or decorates any child class of a GridPanel. This is the only class you need to work with for a DynaGrid.
  • JSORM.ext.DynaGridView, which extends Ext.grid.GridView or decorates any child class of a GridView. You do not need to use this class, as it is created automatically by DynaGrid.
  • JSORM.ext.PagingMemoryProxy, which extends Ext.data.MemoryProxy. You can use this to simulate server-side paging data responses from in-memory stores.

DynaGrid

DynaGrid Creation

To use a dynamic grid, you simply need to use it in place of a normal Ext.grid.GridPanel. All of the rest is automatic.

var grid = new JSORM.ext.DynaGrid({
				width: 220,
				autoScroll: true,
				enableColumnHide: false,
				enableColumnMove: false,
				enableColumnResize: false,
				layout: 'fit',
				columns: [{id: 'name', header: 'Name',sortable: true},{id:'login',header: 'Login',sortable: true}],
			        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
				store: aStore
			}

Alternatively, you can use the Ext.ux alias

var grid = new Ext.ux.grid.DynaGrid({
				width: 220,
				autoScroll: true,
				enableColumnHide: false,
				enableColumnMove: false,
				enableColumnResize: false,
				layout: 'fit',
				columns: [{id: 'name', header: 'Name',sortable: true},{id:'login',header: 'Login',sortable: true}],
			        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
				store: aStore
			}

If you already have a different extension of Ext,grid.GridPanel that you prefer to use, you can use the decorator pattern. Assume you already have an extension named Ext.ux.MyGridPanel.

var grid = new JSORM.ext.DynaGrid(Ext.ux.MyGridPanel,{
				width: 220,
				autoScroll: true,
				enableColumnHide: false,
				enableColumnMove: false,
				enableColumnResize: false,
				layout: 'fit',
				columns: [{id: 'name', header: 'Name',sortable: true},{id:'login',header: 'Login',sortable: true}],
			        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
				store: aStore
			}

DynaGrid Initialization

It is important that you use the paging parameters (start and limit) from the very first time you load the underlying store. If not, the store may try to load the entire data set from the server. This will not break DynaGrid in any way, but will load the entire (possibly very large) data set, thus defeating the purpose of having DynaGrid in the first place.

The initial load is done in one of two ways:

// after aStore is created
aStore.load({params: {start: 0, limit: 50}}); // will load the first 50 records
// at aStore creation
var aStore = new Ext.data.Store({
    // lots of config parameters
    autoLoad({params: {start: 0, limit: 50}});
});

DynaGrid Margins

DynaGrid uses the concept of margins, as in margins of error, to determine how many rows should be above or below the visible rows. DynaGrid determines the number of visible rows, multiplies it by the marginFactor, and loads the right number of rows such that marginFactor*visibleRows are hidden both above and below the visible grid.

For example, assume that you have a grid that is sized to show 20 rows, and the marginFactor is 0.5, which is the default. In that case, DynaGrid will have marginFactor*visibleRows = 0.5*20 = 10 rows above and 10 below. The total number of records in the store at any time, then, will be 40: 10 above, 20 visible, and 10 below.

You can set the marginFactor on DynaGrid instantiation by using the config parameter marginFactor. For example, if you want a marginFactor of 1, which means the same number of rows above and below as is visible, you do the following:

var grid = JSORM.ext.DynaGrid({
    // normal grid configuration parameters
    marginFactor: 1
});

As the user scrolls through the grid, rows that were on one end will appear, while others that were visible will slide out. This will lead to an imbalance in the number of rows. Continuing our previous example, we had visible rows of 20 and marginFactor is 0.5, thus 10 rows above and 10 below. If the user scrolls downwards 2 rows, they will still have 20 visible, but with 12 above and 8 below. The more the user scrolls down, the more rows above and the fewer below.

DynaGrid will rebalance the rows, i.e. remove excess and load extra, when the number of rows is half the margin. Put in other words, when one side is three times the other side, DynaGrid will rebalance. Using the previous example, when there are only 5 rows below and 15 above, DynaGrid will prune the top 5 and load 5 more below, returning to a balance of 10 above and 10 below. Note that the entire time, the same number is visible, in this case 20.

Note that the higher the margin factor, the less frequently the grid will ask the store to go to its server source to load, but the greater the number of records loaded each time, and the more that must be kept in memory. Continuing the previous example, if visible rows is 20, then with a marginFactor of 0.5, every 5 rows of scrolling will lead to a load of 5 rows. On the other hand, with a marginFactor of 2, then loads will happen only every 20 rows, but the load will be 20 rows. Further, 100 rows will be kept in memory, as opposed to 40 with a marginFactor of 0.5.

PagingMemoryProxy

Regular Usage

A PagingMemoryProxy is created exactly like a normal Ext.data.MemoryProxy, but using its own class instead:

var Person = Ext.data.Record.create([{name: 'firstName'},{name: 'lastName'},{name: 'address'}]);
var store = new Ext.data.Store({
	proxy: new JSORM.ext.PagingMemoryProxy(someJson),
	reader: new Ext.ux.JsonReader({
		root: 'person'
	},Person)
});

When you load data, if you pass it the paging options of "start" and "limit", PagingMemoryProxy will respect them and return the records from the in-memory array that match the start and limit indexes. For example, if the json loaded into the proxy is as follows:

var data = {root: [
    {name: "Alice"},
    {name: "Bram"},
    {name: "Charlie"},
    {name: "David"},
    {name: "Elizabeth"},
    {name: "Frank"},
    {name: "Geoffrey"},
    {name: "Helen"},
    {name: "Izzy"},
    {name: "Jack"}
]};

Then passing a start of 1 and limit of 3 will return the records for Bram, Charlie and David.

Special Server Usage

PagingMemoryProxy has a variant that allows you to test data from the server rather than locally. Specifically, if the "data" passed to the constructor is an object with a "url" property, then the data is loaded, in its entirety, from the URL, and passed to the store from the proxy in paging chunks. This allows you to avoid having the entire data set in your program, and significantly eases testing scenarios.

var Person = Ext.data.Record.create([{name: 'firstName'},{name: 'lastName'},{name: 'address'}]);
var store = new Ext.data.Store({
	proxy: new JSORM.ext.PagingMemoryProxy({url: '/path/to/json/file.json'}),
	reader: new Ext.ux.JsonReader({
		root: 'person'
	},Person)
});
Personal tools