We’ve just managed to get the Ext Row Expander plugin embedded in our integration design and working within 3 hours (which we think is reasonably quick and highlights the productivity of ExtJS combined with APEX). The point I’m trying to emphasize is that we will never have to spend anymore time in the future to enable this functionality in any report in any application other than selecting the Ext report template which we have created. This is what templates do, it’s a write once approach, and a massive productivity boost (think of the development cost savings), so spend a little time on them and they’ll definitely reward you. Remember you can subscribe templates in multiple application to 1 master so if you need to make any changes it’s done in a single location, i.e. centralized update.
To enable the row expander functionality in our APEX report we simply set the CSS style for the columns which we want to expand/collapse we simply set a class attribute of “ext-grid-row-expander”, and we can do this for as many columns as we like in the report, or none at all as the JS is all condition based on the contents of our JSON report metatdata object. So how many mouse clicks does that take? Not many…
We simply added the required plugin JS to your page header and for our example we simply created the following attributes in our report JSON object (ext#REGION_ID#) that appears in our page header created by the PLSQL application level process
"columns": [, {
"name": "SELECTION",
"dataIndex": "SELECTION",
"header": "<input type=\"checkbox\" name=\"f10\" value=\"\" onclick=\"toggleAll(\'f01\')\"><span>All<\/span>",
"sortable": false,
"align": "CENTER",
"width": 100
},
{
"name": "NAME",
"dataIndex": "NAME",
"header": "Name",
"sortable": true,
"align": "LEFT",
"width": 100
},
{
"name": "GEONAME_ID",
"dataIndex": "GEONAME_ID",
"header": "Geoname ID",
"sortable": true,
"align": "LEFT",
"width": 100
},
{
"name": "MODIFICATION_DATE",
"dataIndex": "MODIFICATION_DATE",
"header": "Modification Date",
"sortable": true,
"align": "CENTER",
"width": 100,
"renderer": Ext.util.Format.dateRenderer('d-M-Y')
},
{
"name": "POPULATION",
"dataIndex": "POPULATION",
"header": "Population",
"sortable": true,
"align": "RIGHT",
"width": 100
},
{
"name": "LATITUDE",
"dataIndex": "LATITUDE",
"header": "Latitude",
"sortable": false,
"align": "LEFT",
"width": 100
},
{
"name": "LONGITUDE",
"dataIndex": "LONGITUDE",
"header": "Longitude",
"sortable": true,
"align": "RIGHT",
"width": 100
}],
"mapping": [{
"name": "COMMENTS",
"mapping": 0
},
{
"name": "SELECTION",
"mapping": 1
},
{
"name": "NAME",
"mapping": 2
},
{
"name": "GEONAME_ID",
"mapping": 3,
"type": "int"
},
{
"name": "MODIFICATION_DATE",
"mapping": 4,
"type": "date",
"dateFormat": "d-M-Y"
},
{
"name": "POPULATION",
"mapping": 5,
"type": "int"
},
{
"name": "LATITUDE",
"mapping": 6
},
{
"name": "LONGITUDE",
"mapping": 7
}],
"expandTemplate": ["<p><b>Comments<\/b>: {COMMENTS}<\/p>"]
And we then added the following to our report template javascript
/* Row Expander Plugin check */
if (ext#REGION_ID#.plugins.indexOf("expand") !== -1) {
var expander#REGION_ID# = new Ext.grid.RowExpander({
tpl : new Ext.Template(
ext#REGION_ID#.expandTemplate
)
});
ext#REGION_ID#.columns[0] = ExtExpander#REGION_ID#;
}
grid#REGION_ID# = new Ext.grid.GridPanel({
.....
plugins: [summary#REGION_ID#,filter#REGION_ID#,expander#REGION_ID#],
.....
});
Note: in the above javascript I just want to highlight that we initially created the column object with an undefined entry in the beginning as expander rows was enabled (how do we know, because we query the APEX data dictionary and check the column CSS class when building the JSON object), so we need to update this just before we build the grid as when we created our JSON object in the header we didn’t know what the expander object was at the time (ext#REGION_ID#.columns[0] = ExtExpander#REGION_ID#;)
The great thing is that this fits in with the other plugins enabled, summary & filtering! Here’s a screenshot of the end result:

