Extjs GridPanel plugin: Ajax row expander

4 min read >

Extjs GridPanel plugin: Ajax row expander

Engineering Insights & Enterprise solutions

If you were like me in the need to expand the rows of an Extjs GridPanel not using cached data, but rather dynamically through an Ajax request, then you’ve ended in the right place.

The current Extjs GridPanel plugin – RowExpander, located in the examples of Extjs, is good if you happen to have access to that data when the request for filling the GridPanel takes place. But if your request involves querying lots of tables in the database, then you might want to minimize/optimize the HTTP requests and the SQL queries, hence, your optimized Ajax request to fill GridPanel’s content may not bring those details you might need.

This is a good reason for building a RowExpander that would fill up the bodyContent of the GridPanel’s row using an Ajax request.

The following piece of code creates a class called AjaxRowExpander which extends the original RowExpander provided in the Extjs examples. So if you want to use it, you need to also include the RowExpander.js file.

What it does, is pass an URL in the constructor, a URL that will be later used to make the Ajax request. One other thing to notice in the constructor is the disabling of the cache since I needed fresh data every time.

The class overrides the getBodyContent method, in which three things happen:

  1. a temporary body is created, displaying a “Loading…” message. The temporary body is actually a div that will be later filled with the response from the Ajax request. In order to do that, we need to retrieve the exact same div object later when the response gets back from the server. This is why the div gets an id: ‘tmp’ + record.id, so that it can be uniquely identified later.
  2. second, the Ajax request is made, at an URL obtained by concatenating the URL received in the constructor, and the id of the record. A typical URL may look like: “loadPersonDetails.htm?id=“.
  3. the third step (which happens asynchronously) is when the response gets back from the server, and the div created in step 1 is filled with the server’s response
AjaxRowExpander = function(config, previewURL){
    AjaxRowExpander.superclass.constructor.call(this, config, previewURL);
    this.previewURL = previewURL;
    this.enableCaching = false;

Ext.extend(AjaxRowExpander, Ext.grid.RowExpander, {
    getBodyContent : function(record, index){
        var body = ‘
AjaxRowExpander = function(config, previewURL){
    AjaxRowExpander.superclass.constructor.call(this, config, previewURL);
    this.previewURL = previewURL;
’; Ext.Ajax.request({ url: this.previewURL + record.id, disableCaching: true, success: function(response, options) { Ext.getDom(”articleReportsPreview” + options.objId).innerHTML = response.responseText; }, failure: function(error) { alert(DWRUtil.toDescriptiveString(error, 3)); }, objId: record.id }); return body; }, beforeExpand : function(record, body, rowIndex){ if(this.fireEvent(’beforeexpand’, this, record, body, rowIndex) !== false){ body.innerHTML = this.getBodyContent(record, rowIndex); return true; } else{ return false; } } });‘

There is another function from the RowExpander which gets overridden, and that is beforeExpand. This was needed since the original beforeExpand method did not eagerly initialize the row’s body.

And here’s an example of how to use it:

var expander = new AjaxRowExpander({}, ‘loadPersonDetails.htm?id=’);
var cm = new Ext.grid.ColumnModel([
        {header: "Id", dataIndex: 'id', width: 14, align: 'right', defaultSortable: true},
        {header: "Name", dataIndex: 'name', width: 30, sortable: false}

var grid = new Ext.grid.GridPanel({
        height: 500,
        width: 635,
        store: store,
        cm: cm,
        sm: sm,
        viewConfig: {
        plugins: expander

Blogged with Flock

Tags: extjs, gridpanel, plugin, expander, ajax

Unlock innovation and digital transformation for your business.

Get in touch

We are always happy to talk






165 Splaiul Unirii, Timpuri Noi Square,
TN Office 2 building, 4th floor,
District 3, Bucharest, Romania, 030134