ColdFusion 8 Grid Context Menus
ColdFusion 8 has some great AJAX features built in as we all know. One of the more popular tags is the cfgrid in HTML format. This grid as we know really just wraps the Ext 1.1 framework. One question I see often is how can add some context menus to my grid. This would be both when you click on a row in the grid and on the grids header. This tutorial should clear up some of the questions everyone has been asking. First off I need to say this is not perfect. I do tons of Ext 2.0 work and it works great in 2.0 but there is a minor problem and I am sure after this post someone will point out a fix.
Ok, first thing we need to do is create a basic grid for us to use. I am going to use the cfartgallery datasource that is shipped with ColdFusion 8. Basically we just query our database, create an attribute structure (you don't have to do this I just like it this way) and output our grid. If your not sure about the grid code It is pretty basic, just read up on it.
SELECT artistId, firstname, lastname, address, city, state, postalcode, email
FROM Artists
</cfquery>
<cfset args = structNew()>
<cfset args.name = "ArtistGrid">
<cfset args.format = "html">
<cfset args.query = "getArtists">
<cfset args.stripeRows = true>
<cfset args.selectColor = "##D9E8FB">
<cfform>
<cfgrid attributeCollection="#args#">
<cfgridcolumn name="artistid" display="false">
<cfgridcolumn name="firstname" header="First Name">
<cfgridcolumn name="lastname" header="Last Name">
<cfgridcolumn name="email" header="Email Address">
<cfgridcolumn name="address" header="Address">
<cfgridcolumn name="city" header="City">
<cfgridcolumn name="state" header="State">
<cfgridcolumn name="postalcode" header="Zip">
</cfgrid>
</cfform>
Now that we have our grid we need to do a couple things. First we need to call a JavaScript function after our grid loads. To do this I can simply use the ajaxOnLoad tag. This will tell us to call the init method when the page loads. We will get to this function in a second.
The next thing we need to do is include the necessary files to create menus in Ext. A context menu or right click menu is nothing more than a basic menu in Ext. The reason we need to do this is because this page does not use the menu files only a grid so we need to manually include them. I have also chosen to import the aero theme and the menu stylesheets.
<link href="/CFIDE/scripts/ajax/ext/resources/css/ytheme-aero.css" rel="stylesheet" type="text/css">
<link href="/CFIDE/scripts/ajax/ext/resources/css/menu.css" type="text/css" rel="stylesheet"/>
Now for the real magic. Once the grid is created we can add event listeners to the grid. The way we do that is by getting the grid object and calling its addListener method. One of the listeners the Ext framework exposes is the rowcontextmenu listener. This will tell our grid to to listen for context menus. Here we are just using an anonymous function that gets passed the grid object, the row that was click and the event that caused the context menu.
function init(){
grid = ColdFusion.Grid.getGridObject("ArtistGrid");
grid.addListener("rowcontextmenu", function(grid, rowIndex, e) {
var record = grid.getDataSource().getAt(rowIndex); // Get the Record
});
}
</script>
Now we need to create our menu. I am just creating 2 basic menu items that have a click handler. When the menu item is clicked the onClick method is called. In the full source you will see this method just displays an alert box. Next we need to stope the browser for showing its default context menu. We do that by using the stopEvent method passed by our Event Object. Finally where do we show this menu, well we can capture where the user right clicked.
contextMenu.add({text:"Edit Record",handler:onClick});
contextMenu.add({text:"View Record",handler:onClick});
// Stops the browser context menu from showing. e.stopEvent();
// show menu at contextMenu.showAt(e.xy);
And that is all there is to it. Also, now the removed the browsers context menu we have the ability to right click on the the grids header and display those fancy menus. Now remember I told you it was not perfect. There seems to be a couple of CSS issues but nothing major and something I am sure someone will fix. I have some screen shots below and the full source for the example. Please feel free to drop me a question.
Full Example Code
<head>
<title>Basic Grid Example</title>
<script type="text/javascript" src="/CFIDE/scripts/ajax/ext/package/menu/menus.js"></script>
<script type="text/javascript">
function init(){
grid = ColdFusion.Grid.getGridObject("ArtistGrid");
grid.addListener("rowcontextmenu", function(grid, rowIndex, e) {
var record = grid.getDataSource().getAt(rowIndex); // Get the Record
var contextMenu = new Ext.menu.Menu();
contextMenu.add({text:"Edit Record",handler:onClick});
contextMenu.add({text:"View Record",handler:onClick});
// Stops the browser context menu from showing. e.stopEvent();
// show menu at contextMenu.showAt(e.xy);
});
}
function onClick(){
alert("hello")
}
</script>
</head>
<body>
<cfquery name="getArtists" datasource="cfartgallery">
SELECT artistId, firstname, lastname, address, city, state, postalcode, email
FROM Artists
</cfquery>
<cfset args = structNew()>
<cfset args.name = "ArtistGrid">
<cfset args.format = "html">
<cfset args.query = "getArtists">
<cfset args.stripeRows = true>
<cfset args.selectColor = "##D9E8FB">
<cfform>
<cfgrid attributeCollection="#args#">
<cfgridcolumn name="artistid" display="false">
<cfgridcolumn name="firstname" header="First Name">
<cfgridcolumn name="lastname" header="Last Name">
<cfgridcolumn name="email" header="Email Address">
<cfgridcolumn name="address" header="Address">
<cfgridcolumn name="city" header="City">
<cfgridcolumn name="state" header="State">
<cfgridcolumn name="postalcode" header="Zip">
</cfgrid>
</cfform>
<cfset ajaxOnLoad("init")>
<cfsavecontent variable="head">
<link href="/CFIDE/scripts/ajax/ext/resources/css/ytheme-aero.css" rel="stylesheet" type="text/css">
<link href="/CFIDE/scripts/ajax/ext/resources/css/menu.css" type="text/css" rel="stylesheet"/>
</cfsavecontent>
<cfhtmlhead text="#head#">
</body>
</html>



