As you all know by now the grid in ColdFusion 8 is powered by the Ext framework. If you dive into the documentation you will find out that there is more that you can do with it then advertised. We have been looking at ways to customize the grid, today we will learn about event listeners. The grid has the ability to announce events as they are happening even if you are not listening for them. Events can include clicking on a row double clicking on a cell or even using a keyboard shortcut. Just knowing that the gird announces these events will do you no good, you need the ability to listen for them.
The grid gives you 2 methods to listen for events. The following methods will append an event handler to this component the on method is just shorthand for addListener.
- addListener( String eventName, Function handler, [Object scope], [Object options] ) : void
- on( String eventName, Function handler, [Object scope], [Object options] ) : void
2 SELECT artistId, firstname, lastname, address, city, state, postalcode, email
3 FROM Artists
4 </cfquery>
5
6 <cfset args = structNew()>
7 <cfset args.name = "ArtistGrid">
8 <cfset args.format = "html">
9 <cfset args.query = "getArtists">
10 <cfset args.stripeRows = true>
11 <cfset args.selectColor = "##D9E8FB">
12 <cfset args.selectOnLoad = false>
13
14 <cfform>
15 <cfgrid attributeCollection="#args#">
16 <cfgridcolumn name="artistid" display="false">
17 <cfgridcolumn name="firstname" header="First Name">
18 <cfgridcolumn name="lastname" header="Last Name">
19 <cfgridcolumn name="email" header="Email Address">
20 <cfgridcolumn name="address" header="Address">
21 <cfgridcolumn name="city" header="City">
22 <cfgridcolumn name="state" header="State">
23 <cfgridcolumn name="postalcode" header="Zip">
24 </cfgrid>
25 </cfform>
26
27 <cfset ajaxOnLoad("init")>
Now that our grid is setup we can setup our init method. Remember I said ColdFusion makes it easy, I was not lying, the getGridObject will get our grid for us.
2 function init(){
3 //get the grid component
4 grid = ColdFusion.Grid.getGridObject("ArtistGrid");
5 </script>
- bodyscroll : ( Number scrollLeft, Number scrollTop ) - Fires when the body element is scrolled
- cellclick : ( Grid this, Number rowIndex, Number columnIndex, Ext.EventObject e ) - Fires when a cell is clicked
- cellcontextmenu : ( Grid this, Number rowIndex, Number cellIndex, Ext.EventObject e ) - Fires when a cell is right clicked
- celldblclick : ( Grid this, Number rowIndex, Number columnIndex, Ext.EventObject e ) - Fires when a cell is double clicked
- click : ( Ext.EventObject e ) - The raw click event for the entire grid.
- columnmove : ( Number oldIndex, Number newIndex ) - Fires when the user moves a column
- columnresize : ( Number columnIndex, Number newSize ) - Fires when the user resizes a column
- contextmenu : ( Ext.EventObject e )The raw contextmenu event for the entire grid.
- dblclick : ( Ext.EventObject e ) - The raw dblclick event for the entire grid.
- dragdrop : ( Grid this, Ext.GridDD dd, String targetId, event e ) - Fires when dragged row(s) are dropped on a valid DD target
- dragenter : ( Grid this, Ext.GridDD dd, String targetId, event e ) - Fires when the dragged row(s) first cross another DD target while being dragged
- dragout : ( Grid this, Ext.GridDD dd, String targetId, event e ) - Fires when the dragged row(s) leave another DD target while being dragged
- dragover : ( Grid this, Ext.GridDD dd, String targetId, event e ) - Fires while row(s) are being dragged. "targetId" is the id of the Yahoo.util.DD object the selected rows are being dr...
- enddrag : ( Grid this, Ext.GridDD dd, event e ) - Fires when a drag operation is complete
- headerclick : ( Grid this, Number columnIndex, Ext.EventObject e ) - Fires when a header is clicked
- headercontextmenu : ( Grid this, Number columnIndex, Ext.EventObject e ) - Fires when a header is right clicked
- headerdblclick : ( Grid this, Number columnIndex, Ext.EventObject e ) - Fires when a header cell is double clicked
- keydown : ( Ext.EventObject e ) - The raw keydown event for the entire grid.
- keypress : ( Ext.EventObject e ) - The raw keypress event for the entire grid.
- mousedown : ( Ext.EventObject e ) - The raw mousedown event for the entire grid.
- mouseout : ( Ext.EventObject e ) - The raw mouseout event for the entire grid.
- mouseover : ( Ext.EventObject e ) - The raw mouseover event for the entire grid.
- mouseup : ( Ext.EventObject e ) - The raw mouseup event for the entire grid.
- render : ( Grid grid ) - Fires when the grid is rendered
- rowclick : ( Grid this, Number rowIndex, Ext.EventObject e ) - Fires when a row is clicked
- rowcontextmenu : ( Grid this, Number rowIndex, Ext.EventObject e ) - Fires when a row is right clicked
- rowdblclick : ( Grid this, Number rowIndex, Ext.EventObject e ) - Fires when a row is double clicked
- startdrag : ( Grid this, Ext.GridDD dd, event e ) - Fires when row(s) start being dragged

#1 by Michael White on 3/20/08 - 12:58 PM
#2 by Dan Vega on 3/20/08 - 1:00 PM
#3 by Jeff Self on 3/20/08 - 4:45 PM
#4 by Kay Smoljak on 3/21/08 - 12:10 AM
#5 by Dan Vega on 3/21/08 - 10:28 AM
@Kay - Thanks so much. No plans for a book just yet! ha ;)
#6 by Daniel on 3/22/08 - 9:03 AM
Is it possible to know if customer resize or move columns and save this onchange?
#7 by Mark D on 3/31/08 - 12:00 PM
#8 by mp on 5/5/08 - 12:55 PM
Thanks in advance,
mp
#9 by JeffG on 5/17/08 - 9:34 AM
I love your blog and always learn something from your posts.
I have run across something troubling and I hope you can help.
I have been doing some work with cfgrids bound to cfcs.
The site is built on a CF8 server using Fusebox55 as a framework.
I have noticed that each cfgrid consumes a lot of memory, [4-10mb] even when there is only a couple of records.
This memory allocation does not get released when you go to a different page in the site.
The memory is not recovered until the last browser belonging to the session is closed.
If you bounce around in a session for a while with this kind of consumption eventually [not a long time really] the browser crashes.
This occurs in both IE and FF3.
Example: I have several different grids on several tabs on 1 page of the application I am developing. I also have a separate browser that opens with a grid in it [a help index]. What I have seen is that if you go to the section of the site with the grids a block of memory gets consumed each time the page is opened, but it is not released if you navigate away. Spawn the separate window [the help system] a block of memory is consumed. Close and re-open the help window and 4-10mb of memory is consumed but not released each time.
I think this looks like it relates to issues with event listeners generating memory leaks and becoming orphans if they are not destroyed.
I know that event listeners should be destroyed.
But I have not read nor can find nothing about cleaning up after a cfgrid when you go to close a web page.
It is definitely related to the cfgrid I can trace it that far.
Here is a thread where others are discussing the exact same behavior.
http://groups.google.com/group/macromedia.coldfusi...
Have you seen this as an issue?
On a related topic how do I destroy the listeners I create that are watching for rowclick etc.
I read your comment in a post about creating a listener to destroy() cfwindow instances but I can't see how I extend that concept to my cfgrids or to my other listeners.
I am faced with the fact that I will have to remove cfgrd from my project and develop a different solution if this is not correctable.
Do you have any suggestions.
Thanks in advance for any suggestions you may have.
Jeff G
#10 by Matt Gifford on 5/22/08 - 10:42 AM
This is great. Thank you so much.
I'm using the eventListener rowclick, and am receiving the rowIndex.
Does anyone know how I can pass across a value from the query (that row's ID) to the script, so that I can use it in a query call?
#11 by Dan Vega on 5/22/08 - 10:47 AM
#12 by Matt Gifford on 5/22/08 - 10:57 AM
How do I access that variable from the Listener?
#13 by Dan Vega on 5/22/08 - 11:00 AM
function editArtist(grid,rowIndex,e){
var record = grid.getDataSource().getAt(rowIndex);
console.log(record);
}
#14 by Matt Gifford on 5/22/08 - 11:08 AM
I'm really sorry, I'm still stuck on this one. I can see it passing the object via the record variable, but how do I access the individual grid variables from this?
For example, I want to retrieve the UUID from that selected row.
Any help would be greatly appreciated.
#15 by Dan Vega on 5/22/08 - 11:18 AM
var row = grid.getDataSource().getAt(rowIndex);
var artistId = row.data.ARTISTID;
#16 by Brian on 7/30/08 - 9:57 PM
#17 by Brian on 7/30/08 - 11:08 PM
#18 by sneha on 8/1/08 - 8:21 PM
I have two grids (grid1 & grid2). I want grid2 results to be filtered based on grid1 selection (which i was able to do) but initially on page load i want all records to show up on grid2.
This is what i have:
function init(){
//window.filterParam = '';
grid = ColdFusion.Grid.getGridObject("grid1");
grid.addListener("rowclick",setValue);
}
function setValue()
{
//window.filterParam = '';
var grid = ColdFusion.Grid.getGridObject("grid1");
var record = grid.getSelections();
window.filterParam = record[0].data.FIRSTNAME;
var grid2 = ColdFusion.Grid.getGridObject("grid2");
grid2.refresh();
}
function getValue()
{
return window.filterParam;
}
And the bind attribute for grid2 has:
<cfgrid format="html" name="employeeGrid"
bind="cfc:employeeService.getData({cfgridpage},{cfgridpagesize},
{cfgridsortcolumn},{cfgridsortdirection},getValue())"
Whats happening is, on page load all records display on grid2. But when a row from grid1 is clicked, still grid2 shows all records. Only when a second row from grid1 is clicked, results pertaining to previous grid1 selection (not current selection) get filtered in grid2.
I printed 'window.filterParam' when every grid1 row is clicked and it seems to be getting the right value, but for some reason grid2 results aren't getting refreshed.
please someone help!!
#19 by greg on 10/31/08 - 4:20 PM
#20 by Bob R on 12/11/08 - 11:12 AM
I do have one question though, is there a way to tell what cell a user has clicked on. I want to open a window when a user clicks on a cell, unless it is the first cell which contains a check box.
Thanks for you help.
#21 by Bob R on 12/11/08 - 3:03 PM
#22 by Tones411 on 2/18/09 - 11:09 AM
Here's a trick to get it into the head area if you are using some kind of template system:
<cfsavecontent variable="javascript">
<script type="text/javascript">
function init(){
...
}
</script>
</cfsavecontent>
<cfhtmlhead text="#javascript#">
<cfset ajaxOnLoad("init")>
#23 by Nate on 3/20/09 - 3:00 PM
#24 by Gary Habermann on 6/20/09 - 11:53 PM
#25 by Nate on 12/22/09 - 2:18 PM
#26 by Tim on 1/14/10 - 5:37 PM
Thanks for that follow up. I was pulling out my hair trying to get the timing right on applying my column renderers to a cfgrid in a cfwindow. I tried grid.on show/render/afterrender you name it. Finally gave up after seeing your post and just put in a Ext.util.DelayedTask. Works great now :-)
#27 by Tim on 1/14/10 - 6:02 PM
//---------------------------------------------------
// Billing Grid is loaded and ready
billingGridReady = function(){
// format amount columns
var billingGrid = ColdFusion.Grid.getGridObject("billingGrid");
var cm = billingGrid.getColumnModel();
var col;
for (var i=0, count=cm.getColumnCount(); i<count; i++) {
col = cm.getColumnById(cm.getColumnId(i));
if (col.name.substr(0,6) == 'AMOUNT') {
cm.setRenderer(i, Ext.util.Format.numberRenderer('0.00'));
}
}
billingGrid.reconfigure(billingGrid.getStore(),cm);
};
//---------------------------------------------------
#28 by Mike on 4/13/11 - 1:18 PM
#29 by Dan Vega on 4/13/11 - 1:23 PM
#30 by Paul on 5/25/11 - 10:20 AM
I'm just wondering if there is an event listener for the default delete button. I need to fire a function when a row gets removed. I can only seem to find how to add custom delete buttons.
Thanks
#31 by steve on 12/2/11 - 11:07 AM
I'm trying to add a context menu as in this one here:
http://abeautifulsite.net/blog/2008/09/jquery-cont...
In the cfc I added a column, to the query, embedded an icon and I send it to the grid. For it to work, the jquery needs to be initialized looking for the class and img tag every time the data is loaded or refreshed.
I tried an ajaxonload init call, but at that time, the data hasn't loaded yet, so it fires before the data and misses the call.
I put a button on the page and I can click it to activate it on the current results, and it works fine. However, when I page to the next set of records, it loses the call. I would have to click the button again.
The only thing I have seen that makes it work is the mouseover event. But since the event can fire thousands of times, I'm thinking it may have some performance issues on the browser.
any ideas?
My end result is to have a user right click anywhere on a record OR an icon, and have a right click contact menu that would include view/Edit/Delete/add note/make payment/etc... as various options. The script would send the option along with an ID value from the row or ID of the icon clicked and allow coldfusion to handle the rest.
I'm trying to get it active when