View Full Version : TableGridView - 25-50% faster GridView implementation

24 Aug 2010, 5:37 AM
I created a TableGridView extension for Ext 3.2 that uses a <table> to render all rows. In contrast to Animal's TableGridView (http://www.sencha.com/forum/showthread.php?77908-TableGridView-lightweight-GridView-based-upon-a-lt-table-gt), this GridView extension does support column widths and column resizing.

- Reducing the number of DOM elements increases rendering speed (Firefox by about 50%, IE by about 30%, WebKit by about 25%).
- The column width only needs to be specified once for all cells in a column, so changing the column width is very fast (up to 99% depending on the grid size).

- TableGridView does not support enableRowBody (so no RowExpander either).
- Some GridPanel plugins will need to be modified to work with this view.
- Some column renderers might need some changes to display correctly.

Note: I haven't tested this very thoroughly, so please post any problems you find.

9 Sep 2010, 4:48 AM
Does not work, you can provide a small test case?

9 Sep 2010, 5:09 AM
What doesn't work?

Here is an example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ext="http://www.extjs.com" xml:lang="en" lang="en">
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="TableGridView.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base-min.js"></script>
<script type="text/javascript" src="../../ext-all-min.js"></script>
<script type="text/javascript" src="TableGridView.js"></script>
<script type="text/javascript">
Ext.BLANK_IMAGE_URL = '../../resources/images/default/s.gif';
Ext.onReady(function () {
var data = [], columns = [], i, j, r;
for (i = 0; i < 200; i++) {
r = [];
for (j = 0; j < 50; j++) {
r[j] = i * j;
data[i] = r;
for (j = 0; j < 50; j++) {
columns[j] = {
header: 'Field ' + (j + 1),
dataIndex: 'field' + (j + 1)
new Ext.Viewport({
layout: 'fit',
items: [{
xtype: 'grid',
store: data,
columns: columns,
view: new Ext.ux.grid.TableGridView()

9 Sep 2010, 5:47 AM
With the latest beta of 3.3 and does not work.
I tried now with the 3.1 and it works.

Please consider the operation even in this situation:

Version of the animal does not work in this situation.


9 Sep 2010, 7:39 AM
GridView changed in Ext 3.3. You will need an updated version of every grid extension out there!

10 Sep 2010, 12:00 AM
TableGridView does not support enableRowBody (so no RowExpander either).

Could you not leverage <td colspan="n"></td> to assist in row expander support?

10 Sep 2010, 12:20 AM
Yes, I could support row bodies with additional rows, but that would make TableGridView slower. Maybe in a separate class.

I'm also thinking about creating a TableGroupingView that uses a <tbody> for every group.

10 Sep 2010, 5:26 AM
GridView changed in Ext 3.3. You will need an updated version of every grid extension out there!

Condor, is there any info on what's changed that will break all grid extensions in 3.3?

10 Sep 2010, 5:39 AM
The main difference is that renderUI is split into two methods:
1. renderUI does not actually render the UI, but only returns the HTML content to render the grid.
2. afterRenderUI contains all old renderUI code that executed after the grid was rendered.

25 Oct 2010, 1:20 AM
Hello condor.
You can post the version of this extension for Ext 3.3?

25 Oct 2010, 1:30 AM
I'll work on it, but I'm rather busy now, so it could take some time.

26 Oct 2010, 2:54 PM
hi condor and community,

i hope it is ok if i port this one over to ext 3.3.0.
as condor mentioned, it is now afterRenderUI, so we had to change 6 letters inside the code (line 170).

kind regards

26 Oct 2010, 11:22 PM
Yes, now it works.
The version of Animal has a very nice thing for me.
The columns are automatically sized.
It is also possible to implement here?

27 Oct 2010, 1:26 AM
Yes, the DOM structure would allow for width:auto, but the GridView implementation would have to be adapted to get the width of the auto width columns after they have rendered.

Steffen Hiller
7 Nov 2010, 7:55 AM
My Ext.ux.PrinterFriendly plugin works pretty much the same way. Allows printing + has better performance for displaying/printing large datasets. But any additional UI features that you don't need for printing are disabled/removed.

Thanks tobiu for the afterRenderUI thing, that was the only thing that broke my plugin in 3.3.0 as well.

21 Feb 2011, 4:58 PM
Hi Condor,
I am working with 3.2.1 and after fixing a couple of things in your extension i was able to use it in my grid as is. I have to make the grids we are using 508 compliants and one of the violations with the current implementation of the GridPanel is that
1) Rows must be associated with the proper header
2)Rows and headers must belong to the same table.

With your component i was able to achieve 1) partly as now all rows belong to the same table. I tried building on your component to have the Grid header and the grid body all be part of the same table. I have been at it all day now and I am stuck so i kindly request your and the community's help. Basically I get the grid to render with the following problems:

The width on the table row elements is not properly calculated. The headers are rendered fine but the row elements themselves are out of wack.

Here is what it look like:


Here are the changes i made to your code, as well as the overrides i brought in from GridView.js:

initTemplates: function () {
var ts = this.templates || {};
ts.master = new Ext.Template(
'<div class="x-grid3" hidefocus="true">',
'<div class="x-grid3-viewport">',
'<table class="x-grid3-row-table ux-table-grid " border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
'<thead style="{ostyle}" class="x-grid3-header x-grid3-header-inner x-grid3-header-offset"><tr class="x-grid3-hd-row">{headers}</tr></thead>',
'<tbody class="x-grid3-scroller x-grid3-body" style="{bstyle}">{body}</tbody>',
'<div class="x-grid3-resize-marker">&#160;</div>',
'<div class="x-grid3-resize-proxy">&#160;</div>',

ts.header = new Ext.Template('{headers}');

ts.hcell = new Ext.Template(
'<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
'{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
if (!ts.body) {
ts.body = new Ext.Template(


if (!ts.col) {
ts.col = new Ext.Template(
'<col style="{style}" />'
if (!ts.row) {
ts.row = new Ext.Template(
'<tr class="x-grid3-row {alt}" style="{tstyle}">{cells}</tr>'
if (!ts.cell) {
ts.cell = new Ext.Template('<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css} x-grid3-cell-inner x-grid3-col-{id}" style="{style}" tabIndex="0" {cellAttr} unselectable="on" {attr}>',
this.templates = ts;
getRows: function () {
return this.hasRows() ? this.mainHd.dom.tBodies[0].rows: [];
getCols: function() {
return this.hasRows() ? this.mainHd.childNodes : [];

I have also updated renderUI to render everything but the table rows:

renderUI: function () {
var templates = this.templates,
cols = [],
col = this.templates.col,
i, len = this.cm.getColumnCount(),
header = this.renderHeaders(),
body = '&#160;';
for(i = 0; i < len; i++) {
style: this.getColStyle(i)
var html = templates.master.apply({
body: body,
headers: header,
ostyle: 'width:' + this.getOffsetWidth() + ';',
bstyle: 'width:' + this.getTotalWidth() + ';'
var g = this.grid;
g.getGridEl().dom.innerHTML = html;
Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
this.scroller.on('scroll', this.syncScroll, this);
if (g.enableColumnResize !== false) {
this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
if (g.enableColumnMove) {
this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
if (g.enableHdMenu !== false) {
this.hmenu = new Ext.menu.Menu({
id: g.id + '-hctx'
itemId: 'asc',
text: this.sortAscText,
cls: 'xg-hmenu-sort-asc'
}, {
itemId: 'desc',
text: this.sortDescText,
cls: 'xg-hmenu-sort-desc'
if (g.enableColumnHide !== false) {
this.colMenu = new Ext.menu.Menu({
id: g.id + '-hcols-menu'
scope: this,
beforeshow: this.beforeColMenuShow,
itemclick: this.handleHdMenuClick
this.hmenu.add('-', {
itemId: 'columns',
hideOnClick: false,
text: this.columnsText,
menu: this.colMenu,
iconCls: 'x-cols-icon'
this.hmenu.on('itemclick', this.handleHdMenuClick, this);
if (g.trackMouseOver) {
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
if (g.enableDragDrop || g.enableDrag) {
this.dragZone = new Ext.grid.GridDragZone(g, {
ddGroup: g.ddGroup || 'GridDD'

And the render functions:

renderBody: function () {
var cols = [],
i, len = this.cm.getColumnCount(),
col = this.templates.col,
rows = this.renderRows();
if (!rows) {
return '&#160;';

return this.templates.body.apply({rows: rows, tstyle: 'width:' + this.getTotalWidth() + ';'});
renderHeaders : function()
var cm = this.cm,
ts = this.templates,
ct = ts.hcell,
cb = [],
p = {},
len = cm.getColumnCount(),
col = this.templates.col,
last = len - 1;

for (var i = 0; i < len; i++)
p.id = cm.getColumnId(i);
p.value = cm.getColumnHeader(i) || '';
p.style = this.getColumnStyle(i, true);
p.tooltip = this.getColumnTooltip(i);
p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');

if (cm.config[i].align == 'right')
p.istyle = 'padding-right:16px';
delete p.istyle;
cb[cb.length] = ct.apply(p);
return ts.header.apply({headers: cb.join('')});
//return ts.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'});

Thanks in advance

24 Feb 2011, 12:51 AM
user kevin0128 seems to be a bot. he exactly reposted:


with 2 spam-links. better block him and remove the posting.

best regards

25 Feb 2011, 2:34 AM
Yes, the DOM structure would allow for width:auto, but the GridView implementation would have to be adapted to get the width of the auto width columns after they have rendered.

I'd like to see this functionality.
You have a little 'time to implement it?