PDA

View Full Version : Extension or Improvement for Ext.ux.RowExpander for deferred processing



Jan (HL)
12 Jan 2012, 5:26 AM
Hi,

when using the Ext.ux.RowExpander everything works fine now. Several bugs with non expanded rows seems to be fixed (see http://www.sencha.com/forum/showthread.php?146872-RowExpander-and-grid-updates.-How-to-keep-rows-expanded, http://www.sencha.com/forum/showthread.php?125907-FIXED-RowExpander-bug-in-getting-gridview).

At first, the standard markup was built by a template like that: '<img src="{src}"/>'. But since Ext JS4 and the new Expander have a new plugin/feature system, the RowExpander's template will actually used for all (visible) rows, both collapsed and expanded ones.

In a special case I have to defer the rendering when dealing with several bigger images per row. (The body of the expanded view contains n images which should not loaded for every row until the row will expanded.) In order to do that, I changed the template to something like that: '<img pre-src="{src}" />' Of course, this will treat by the browser as an empty image.

When a specific row was expanded (and the event expandbody was fired), the already available markup have to be changed.



grid.getView().on('expandbody', function(expander, record, el, rowIndex){/*do something*/}, this);


This works fine until the store reloads the rows when rows are still expanded. After reloading the data, the grid/view will rerender the recent expanded rows but not with calling toggleRow(i) internally. However, because of that the expandbody event will be never fired, "my defer-render solution" will not work anymore.

In a quick solution, I'd just make two extension which overrides Ext.ux.RowExpander.init and adds a new util method.

#1 Catching each store.load and refresh the expanded rows.



Ext.override(Ext.ux.RowExpander, {
init : function(grid) {
this.callOverridden(arguments);


grid.store.on('load', function() {
this.refreshExpandeds();
}, this);
}
});


#2 Loop for each expanded record/row (using the internally recordsExpanded property) and fire expandbody


Ext.override(Ext.ux.RowExpander, {
refreshExpandeds : function() {
var me = this, store = null;


// Avoid npe ("no view" is possible if this was called before the component is actually finished rendering).
if (me.view) {
store = me.view.up('*').store;
}


if (!store) {
return;
}


Ext.iterate(this.recordsExpanded, function(id, expanded) {
var rowIdx = store.findExact('id', id); // by offset?
if (expanded && rowIdx >= 0) {


var rowNode = this.view.getNode(rowIdx), row = Ext.get(rowNode);
var nextBd = Ext.get(row).down(this.rowBodyTrSelector), record = this.view.getRecord(rowNode), grid = this.getCmp();


this.recordsExpanded[record.internalId] = true;
this.view.fireEvent('expandbody', rowNode, record, nextBd.dom);


// If Grid is auto-heighting itself, then perform a component layhout to accommodate the new height
if (!grid.isFixedHeight()) {
grid.doComponentLayout();
}
this.view.up('gridpanel').invalidateScroller();


}
}, me);
}
});


I'm just copyied the code from toggleRow and cut the collapse-stuff away. The purpose is only: Re-fire expandbody for all records in expandRecords where value is true.

Any suggestions? Any hints? Any problems?

Another possible option could be an additional event which will fired by the plugin itself.

mitchellsimoens
12 Jan 2012, 8:13 AM
It makes sense that the expandbody event doesn't fire when the rows are rerendered and the existing rows that were expanded are shown expanded

I would probably create my own event as to not mess with the plugin's functionality.

Jan (HL)
12 Jan 2012, 9:55 AM
It makes sense that the expandbody event doesn't fire when the rows are rerendered and the existing rows that were expanded are shown expanded

I would probably create my own event as to not mess with the plugin's functionality.

Well, and where will you integrate and attach your own event? The only option is overriding/extending the init-method in the plugin itself or is there something I'd missed?
So instead of calling the "refreshExpandeds" directly, I can fire a special event and implement it later. However, this is not far way from a MyRowExpander, too.