-
17 Dec 2007 4:10 AM #1
Extending the RowExpander Plugin
Extending the RowExpander Plugin
I've just put up a post on my blog about Extending the RowExpander Plugin, complete with the source and a link to the example page. Basically, I wanted the ability to pass a new argument into the rowexpander, a function reference to be called on expansion. I wanted the ability to populate the expanded area, at the time of expansion, with an Ajax call. Afterwards I showed it to Rey [Bango], who said "get an example up and get it on the forums." So here I am.
You can get the full source of the example from the post, but here's the plugin itself:
After that all you need is a function, and the config to point to it:Code:/* * Ext JS Library 2.0 * Copyright(c) 2006-2007, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license * * MODIFIED: SGB [12.12.07] * Added support for a new config option, remoteDataMethod, * including getter and setter functions, and minor mods * to the beforeExpand and expandRow functions */ Ext.grid.RowExpander = function(config){ Ext.apply(this, config); Ext.grid.RowExpander.superclass.constructor.call(this); if(this.tpl){ if(typeof this.tpl == 'string'){ this.tpl = new Ext.Template(this.tpl); } this.tpl.compile(); } this.state = {}; this.bodyContent = {}; this.addEvents({ beforeexpand : true, expand: true, beforecollapse: true, collapse: true }); }; Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, { header: "", width: 20, sortable: false, fixed:true, dataIndex: '', id: 'expander', lazyRender : true, enableCaching: true, getRowClass : function(record, rowIndex, p, ds){ p.cols = p.cols-1; var content = this.bodyContent[record.id]; if(!content && !this.lazyRender){ content = this.getBodyContent(record, rowIndex); } if(content){ p.body = content; } return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed'; }, init : function(grid){ this.grid = grid; var view = grid.getView(); view.getRowClass = this.getRowClass.createDelegate(this); view.enableRowBody = true; grid.on('render', function(){ view.mainBody.on('mousedown', this.onMouseDown, this); }, this); }, getBodyContent : function(record, index){ if(!this.enableCaching){ return this.tpl.apply(record.data); } var content = this.bodyContent[record.id]; if(!content){ content = this.tpl.apply(record.data); this.bodyContent[record.id] = content; } return content; }, // Setter and Getter methods for the remoteDataMethod property setRemoteDataMethod : function (fn){ this.remoteDataMethod = fn; }, getRemoteDataMethod : function (record, index){ if(!this.remoteDataMethod){ return; } return this.remoteDataMethod.call(this,record,index); }, onMouseDown : function(e, t){ if(t.className == 'x-grid3-row-expander'){ e.stopEvent(); var row = e.getTarget('.x-grid3-row'); this.toggleRow(row); } }, renderer : function(v, p, record){ p.cellAttr = 'rowspan="2"'; return '<div class="x-grid3-row-expander"> </div>'; }, beforeExpand : function(record, body, rowIndex){ if(this.fireEvent('beforexpand', this, record, body, rowIndex) !== false){ // If remoteDataMethod is defined then we'll need a div, with a unique ID, // to place the content if(this.remoteDataMethod){ this.tpl = new Ext.Template("<div id='remData" + rowIndex + "' class='rem-data-expand'><\div>"); } if(this.tpl && this.lazyRender){ body.innerHTML = this.getBodyContent(record, rowIndex); } return true; }else{ return false; } }, toggleRow : function(row){ if(typeof row == 'number'){ row = this.grid.view.getRow(row); } this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row); }, expandRow : function(row){ if(typeof row == 'number'){ row = this.grid.view.getRow(row); } var record = this.grid.store.getAt(row.rowIndex); var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); if(this.beforeExpand(record, body, row.rowIndex)){ this.state[record.id] = true; Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded'); if(this.fireEvent('expand', this, record, body, row.rowIndex) !== false){ // If the expand event is successful then get the remoteDataMethod this.getRemoteDataMethod(record,row.rowIndex); } } }, collapseRow : function(row){ if(typeof row == 'number'){ row = this.grid.view.getRow(row); } var record = this.grid.store.getAt(row.rowIndex); var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); if(this.fireEvent('beforcollapse', this, record, body, row.rowIndex) !== false){ this.state[record.id] = false; Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); this.fireEvent('collapse', this, record, body, row.rowIndex); } } });
Code:// FUNCTION: getMyStuff // @param record : actual record in grid row // @param index : row index calling the function function getMyStuff(record,index){ // Using JQuery to 'load' the expanded row with content pulled remotely $('#remData'+index).load('tester.html'); }; var expander = new xg.RowExpander({ remoteDataMethod : getMyStuff });--
Steve "Cutter" Blades
Adobe Community Professional - ColdFusion
Adobe Certified Professional - Advanced Macromedia ColdFusion MX 7 Developer
_____________________________
Blog: Cutter's Crossing
Co-Author "Learning Ext JS 3.2"
-
17 Dec 2007 6:52 AM #2
I have to test this out... but wow... This is very similar to what I had in mind. I may still want to have a container (so that I can load what ever I want there, like say a remote component or another grid etc..) in the expanded section but this is the right direct for it.
Ramki
-
17 Dec 2007 7:36 AM #3
It's in there
It's in there
Thanks Ramki. Actually the call to the remote method will automatically create a container object in the expanded area. There's more info in the blog posting.
--
Steve "Cutter" Blades
Adobe Community Professional - ColdFusion
Adobe Certified Professional - Advanced Macromedia ColdFusion MX 7 Developer
_____________________________
Blog: Cutter's Crossing
Co-Author "Learning Ext JS 3.2"
-
17 Dec 2007 9:08 AM #4
-
21 Dec 2007 4:47 AM #5
I'm trying to use the row expander on my code but its not working..
Edit: Nevermind, solved the problem and its working now..
http://www.ufu.br/ramais/
I'm getting data remotely from a database (ramais.php), so now i need to find out how to get this data remotely and show it on the grid (ramais.js).
-
21 Dec 2007 11:33 AM #6
Thanks
Thanks
Thank you very much Cutter for this plugin,
but I am in need of some more functionality and right now I don't know how to do this. (Never coded a plugin yet, but the rowExpander is that nice I really want to have it)
Two things are missing:
1) I attached a 'celldblclick' event to the grid, thought when the row gets expanded, the visible expanded area doesn't have this event, how can I also attach the celldblclick event to the rowExpander's area for that row?
2) When I have a row expanded and showing the rowExpander, meanwhile updating the grid's datastore (though refreshing the grid), it will show all rows collapsed, even if some of them before the update expanded but the ICON's doesn't get changed. I tried adding an event to the datastore, which then will check all rowExpander.state for that row and replaceClass the Icon but the problem is state only stores the id of the row not the rowIndex itself.
Code:ds.reload( // reload the datastore { callback : function(r, options, success) { if(success) { var expander = XXX.getExpander(); // find all collapsed RowExpander because they won't reset them theirself when the Grid/Store get's updated if(expander.state) { for(row in expander.state) { if(expander.state[row]) // when it was collapsed while updating, it will still show the wrong icon, fix this { expander.state[row] = false; // NEED ROWINDEX HERE NOT ROW! Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); } } } }
Please someone help me!
Regards,
Iveco
-
2 Jan 2008 11:21 PM #7
RowExpander
RowExpander
I find this more convenient
thanCode:Ext.get('remData'+index).load({ url: "tester.html", scripts: true, params: "param1=foo¶m2=bar", text: "Loading Detailed Information..." });
Great plugin..Code:$('#remData'+index).load('tester.html');
thanksLast edited by mystix; 4 Jan 2008 at 12:05 PM. Reason: use [code][/code] tags
-
4 Jan 2008 9:01 AM #8
Got this fixed by using "rowdblclick".
Got this fixed by using:
(dont forget to reset the state's with the for loop I posted more top)Code:Ext.select('div.x-grid3-row-expanded').replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
Regards,
Iveco
-
25 Mar 2008 8:31 PM #9
Thoughts
Thoughts
Hi CutterBl, I was wonder if you could give me a hand on a dilemma I'm having using RowExpander. I want to render components that I've executed multiple times. I know you can't render a component multiple times, but it seems like a waste to rebuild each time someone clicks the expander on my grid. Here's my forum post; http://extjs.com/forum/showthread.ph...ander+multiple
Based on your post, I'm thought you'd know the answer. BTW I'm a CF dev guy myself.
NNo longer a Newbie
-
1 May 2008 12:22 PM #10
Thanks for the great work
Thanks for the great work
Hi CutterBl
Thanks for the great plugin ... works like a charm ... saved me hours of work.


Reply With Quote
