If you were like me in the need to expand the rows of a 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, 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 creating, 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. 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 =
Loading…

’; 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 overrided, and that is beforeExpand. This was needed since the original beforeExpand method did not eagerly initialized the row’s body.

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

var expander = new AjaxRowExpander({}, ‘loadPersonDetails.htm?id=);
var cm = new Ext.grid.ColumnModel([
        expander,
        {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: {
                forceFit:true,
                enableRowBody:true,
                showPreview:false
        },
        plugins: expander
});

Blogged with Flock

Tags: , , , ,

4 responses to “Extjs GridPanel plugin: Ajax row expander

  1. great article. I’m doing something similar.

    Some typos need to be fixed for it to work:
    ”articleReportsPreview” => “tmp”

    Thanks

  2. I am new to using Ext. could you provide a full example (including HTML) for you tutorial so that I can see how everything fits together.

    Thanks,
    -Rich

  3. Nice article indeed. I’d change 2 places in the code though:

    var bodyId = Ext.id();
    var body = ‘Loading…’;

    and then in the success handler:

    Ext.getDom(bodyId).innerHTML = response.responseText;

    This way you get unique IDs for every element and you’re “independent” on manually assignedn IDs.

Leave a Comment:

Your email address will not be published. Required fields are marked *