This week must be grid week. First we have Bruce Phillips' post on cfgrid last night, and today Todd Sharp posted on it as well. I thought I'd follow the crowd and share a tip as well. How do you do something (anything) when a user clicks on a grid, specifically when using the new HTML cfgrid in ColdFusion 8?
Technically there isn't a attribute that you can add to the grid itself. However, other form fields can easily bind to the grid itself. So if you wanted to build an edit form, for example, that is pretty easy (and again, see Bruce Phillips' post). But what if you wanted more fine grained control? This is where CFAJAXPROXY comes in. Now if you are like me - you looked at the docs on CJAJAXPROXY and were impressed with how cool it is to be able to create a connection to a CFC. That's amazing, and in my mind, I think it is the most impressive new feature in ColdFusion 8. But what people may miss (I know I did!) is that CFAJAXPROXY has a whole other... "mode" we shall call it, that lets the tag act in a complete separate manner. In fact, it is so different I'm not quite sure why another tag wasn't made, like CFBIND for example. This other mode takes one main attribute, bind. You can also use a onSuccess and onError attribute. In this mode, the tag simply acts as a listener. So image my grid is named entries. I can bind to it like so:1 <cfajaxproxy bind="javascript:noteChange({entries.title})">
All this says is - when the grid changes - call a JavaScript function and pass the value of the Title column. I could also use a CFC or CFM bind as well, but you get the idea. Again, I think CFBIND would be a better name since in this form the tag isn't creating a proxy object for a remote CFC. But that's neither here nor there - lets get back to the original question - how do I react to a grid change?
First you need to figure out what values you want. In my code sample above, I grabbed the title column. If I wanted something different, like ID, I'd do:
1 <cfajaxproxy bind="javascript:noteChange({entries.id})">
Or I can do both:
1 <cfajaxproxy bind="javascript:noteChange({entries.title},{entries.id})">
Now for a complete example:
1 <cfajaxproxy bind="javascript:noteChange({entries.title},{entries.id})">
2
3 <script>
4 function noteChange(title,id) {
5 alert(title+' '+id);
6 }
7 </script>
8
9 <cfquery name="entries" datasource="blogdev">
10 select *
11 from tblblogentries
12 limit 0,10
13 </cfquery>
14
15 <cfform name="test">
16 <cfgrid autowidth="true" name="entries" format="html" query="entries" pageSize="10">
17 <cfgridcolumn name="id" display="false">
18
19 <cfgridcolumn name="title" header="Title">
20 <cfgridcolumn name="posted" header="Posted">
21 </cfgrid>
22 </cfform>
In this example I'm loading up my HTML grid with a query (yes, you don't have to use Ajax for HTML grids). On the top of my template I bound my JavaScript function to the entries grid. Whenever I selected an entry in my grid, an alert will be fired.
I want to point out one last thing. Take a look at the first cfgridcolumn. Why do I have a column that I don't bother displaying? When you specify the columns to show - you are also limiting the data actually stored in the grid. If I didn't have that hidden column there, I wouldn't be able to use the ID column in my bind.
2
3 <script>
4 function noteChange(title,id) {
5 alert(title+' '+id);
6 }
7 </script>
8
9 <cfquery name="entries" datasource="blogdev">
10 select *
11 from tblblogentries
12 limit 0,10
13 </cfquery>
14
15 <cfform name="test">
16 <cfgrid autowidth="true" name="entries" format="html" query="entries" pageSize="10">
17 <cfgridcolumn name="id" display="false">
18
19 <cfgridcolumn name="title" header="Title">
20 <cfgridcolumn name="posted" header="Posted">
21 </cfgrid>
22 </cfform>
Comment 1 written by Steve Sequenzia on 9 August 2007, at 5:34 PM
Thanks to your help I have got some pretty cool grids working by binding to a cfdiv.
Here is a little demo of one.
http://demo.thinksys.com/cf8/cfgrid/contacts.cfm
Thanks again for all the help.
Comment 2 written by Will on 9 August 2007, at 7:19 PM
Comment 3 written by Raymond Camden on 9 August 2007, at 8:03 PM
Comment 4 written by Steve Sequenzia on 9 August 2007, at 8:15 PM
Comment 5 written by Will on 9 August 2007, at 9:04 PM
Comment 6 written by Raymond Camden on 10 August 2007, at 7:36 AM
Comment 7 written by Will on 10 August 2007, at 9:00 AM
Comment 8 written by Abul on 10 August 2007, at 10:02 AM
Is their a way to add a image to the data grid?
Your this example is coooooooooooool.
Abul
Comment 9 written by Raymond Camden on 10 August 2007, at 11:28 AM
<cfloop query="getData">
<cfset querySetCell(getData, "test", "<img src='http://www.coldfusionjedi.com/images/me.jpg'>", currentROw)>
</cfloop>
I'll do a full demo later today.
@Will: I don't think so.
Comment 10 written by Marty McGee on 12 August 2007, at 7:44 PM
Comment 11 written by Steve Sequenzia on 12 August 2007, at 10:07 PM
I just added the code to the bottom of the demo page. Let me know if you have any questions that I can help with.
I also did a demo with two connected grids. Here is a demo of it:
http://demo.thinksys.com/cf8/cfgrid/2grids.cfm
Comment 12 written by Marty McGee on 12 August 2007, at 10:27 PM
SWEET! Thanks for doing this. Just so others can follow along, Steve Sequenzia has offered two code examples for binding data 1) to a cfdiv, and 2) to a second cfgrid on the same page, based on a cfgrid row click (awesome):
1) cfgrid-to-cfdiv example:
http://demo.thinksys.com/cf8/cfgrid/contacts.cfm
2) cfgrid-to-cfgrid example:
http://demo.thinksys.com/cf8/cfgrid/2grids.cfm
Thanks Steve! I'm sure this will be very helpful for readers.
Comment 13 written by Mike Sprague on 14 August 2007, at 1:08 PM
Comment 14 written by Tony Garcia on 17 August 2007, at 6:11 AM
If you do a 'veiw source' on those pages, though, you can see that there are a bunch of .js files callled at the top. Anyone know how much file size overhead this stuff is adding??
Comment 15 written by Tony Garcia on 17 August 2007, at 12:15 PM
HTML: 3.1 kb
CSS: 6.7 kb
Javascript: 435 kb!
Wow. All these cool AJAX tricks that you can do with CF8 look cool. But a simple page like this weighing in at almost a half megabyte, you better hope none of your users are still on dialup....
Comment 16 written by Will on 17 August 2007, at 2:45 PM
http://alex.dojotoolkit.org/shrinksafe/
I did it for the Spry js files and they all still work perfectly but are a fraction of their original size.
(original blog link to Rey's post : http://www.reybango.com/index.cfm/2007/7/22/Compre...)
Comment 17 written by Raymond Camden on 17 August 2007, at 2:50 PM
Comment 18 written by Tony Garcia on 17 August 2007, at 4:47 PM
Comment 19 written by Peter Swanson on 21 August 2007, at 6:54 PM
Nice post. However, I think I've found a bug. If you click on a title, the javascript popup displays with the title and the ID just fine. However, if you close the popup window, then click on the same title again, no popup appears. I know this is a minor issue, however, I believe some users will invariably close the window, then want to see the same info again.
How to get around this one?
Thanks,
Peter
Comment 20 written by Raymond Camden on 22 August 2007, at 8:19 AM
<cfajaxproxy bind="javascript:noteChange({entries.title@mousedown},{entries.id@click})">
but it didn't work. Notice I tried both mousedown and click.
Comment 21 written by Camilo on 1 September 2007, at 9:56 PM
I was studying the code, and could not duplicate the examples posted, can you Steve Sequenzia please post a zip of the files, so that I can study the source, along with any one else for the matter?
a studying student,
Camilo
Comment 22 written by Steve Sequenzia on 1 September 2007, at 11:15 PM
http://demo.thinksys.com/cf8-grid-examples.zip
Let me know if I can help.
-Steve
Comment 23 written by Camilo on 2 September 2007, at 12:35 AM
the code could not find the cfc
it is in the same directory, and still error. But I have the code, and this has greatly help me out. thanks for giving me the leg up with this ;-)
Comment 24 written by Camilo on 2 September 2007, at 1:38 AM
There is a lot that I can learn from from everyone here !
Comment 25 written by Matteo Stagi on 14 September 2007, at 7:46 AM
<script>
function UpdateFromGrid(gridname,id) {
ColdFusion.navigate('newseditor.cfm?action=update&ID='+id,'CentralAdmin');
</script>
And
<cfajaxproxy bind="javascript:UpdateFromGrid('SearchResults',{SearchResults.id})">
<cfajaxproxy bind="javascript:UpdateFromGrid('LastNews',{LastNews.id})">
Where SearchResults and LastNews are the two cfgrids and CentralAdmin is the cflayout.
But I had the problem of selecting the previous selected row, arised by Peter. This is a problem in particular if your search query returns just one row. You can click on it just once. This other great article by Raymond (http://www.coldfusionjedi.com/index.cfm/2007/8/20/...) suggested my the solution:
<script>
function UpdateFromGrid(gridname,id) {
ColdFusion.navigate('newseditor.cfm?action=update&ID='+id,'CentralAdmin');
mygrid = ColdFusion.Grid.getGridObject(gridname);
sm = mygrid.getSelectionModel()
sm.clearSelections(false);
</script>
Unfortunately this didn't work. The selection was cleared but the onChange event was still not fired when selecting again a previously selected row.
Studying cfgrid.js I think to have finally find the solution:
<script>
function UpdateFromGrid(gridname,id) {
ColdFusion.navigate('newseditor.cfm?action=update&ID='+id,'CentralAdmin');
mygrid = ColdFusion.Grid.getGridObject(gridname);
sm = mygrid.getSelectionModel()
sm.clearSelections(false);
ColdFusion.objectCache[gridname].selectedRow=-1;
</script>
This worked for me. Now I have two different grid controlling a cflayout and you can click on previously clicked row and have the action fired.
Comment 26 written by Neil on 8 October 2007, at 5:19 PM
Thanks so much for this very useful post. The CF 8 docs are very obtuse on this point; they make it seem like you can just use the cfgrid's onchange event listener. However, onchange doesn't seem to work in this context. Your post has saved the day after about 4-6 hours of searching.
Thanks!
-Neil
Comment 27 written by Michael Skinner on 31 October 2007, at 1:03 PM
Comment 28 written by Raymond Camden on 31 October 2007, at 1:08 PM
Comment 29 written by Michael Skinner on 31 October 2007, at 1:33 PM
Comment 30 written by Dave Phipps on 10 December 2007, at 11:09 AM
I have a fuseaction that sets up the cflayout. A default tab has another fuseaction as its source. This tab contains a cfgrid which when a row is click it fires the noteChange function which creates a new tab and uses another fuseaction as the source also passing the id in the source url.
How do I pick up that id within the new tab?
Here's the javascript:
<script>
noteChange = function(orderid) {
var newTab = 'odetail_' + orderid;
var newName = 'Order Details:- ' + orderid;
var oUrl = 'index.cfm?page=admin.orderDetail&orderid=' + orderid;
ColdFusion.Layout.createTab('tabcontainer',newTab,newName,oUrl,{closable:true});
ColdFusion.Layout.selectTab('tabcontainer',newTab);
}
</script>
Also, notice that I had to define the function as noteChange = function() {}
rather than just function noteChange() {}
I read in the docs that this is something to do with the fact that the script is running from within a tab rather than the top level page.
Comment 31 written by Dave Phipps on 10 December 2007, at 11:11 AM
Comment 32 written by sneha on 2 August 2008, at 2:50 PM
bind="cfc:employeeService.getData({cfgridpage},{cfgridpagesize},
{cfgridsortcolumn},{cfgridsortdirection},{grid1.FirstName})"
i just don't know whats getting passed in {grid1.FirstName} the first time page loads. The grid is always blank on page load. Only when a row is clicked, results are filtered in grid2.
I've been scratching my head for hours..unable to find whats wrong..pls help someone..
Comment 33 written by Matts on 10 February 2009, at 6:43 PM
http://www.rgpc.ca/resource/
Grid click opens a cfwindow
Click on the [X] or a close window hyperlink calls a javascript which runs
ColdFusion.Window.destroy('window_name',true);
BUT, if the user then clicks on the same row in the grid, nothing happens. They have to click on a different grid row to open (create) another window.
Any ideas how to fix?
<script language="javascript">
function noteChange(id) {
ColdFusion.Window.create('resource_detail', 'Resource Details', 'http://www.rgpc.ca/resource/resource.cfm?id=' + id, {modal:false, width:<cfoutput>#cfwindow_width#</cfoutput>, height:<cfoutput>#cfwindow_height#</cfoutput>, closable:true, x:400, y:100});
ColdFusion.Window.onHide('resource_detail', destroy_window);
}
function destroy_window() {
ColdFusion.Window.destroy('resource_detail',true);
</script>
any help much appreciated!
Cheers,
Matts
Comment 34 written by Matts on 10 February 2009, at 8:18 PM
ColdFusion.objectCache['resource_list'].selectedRow=-1;
where 'resource_list' is the name of the cfgrid
I've added this in various places in my javascript -- no js errors are posted, but also no luck!
Matts
Comment 35 written by Matts on 10 February 2009, at 8:31 PM
mygrid = ColdFusion.Grid.getGridObject('resource_list');
sm = mygrid.getSelectionModel()
sm.clearSelections(false); ColdFusion.objectCache['resource_list'].selectedRow=-1;
Hope this helps someone out there!
Comment 36 written by Tones411 on 18 February 2009, at 10:00 AM
Comment 37 written by James on 19 March 2009, at 9:20 AM
Comment 38 written by Clay on 29 September 2009, at 1:27 PM
Here is my code...
function showDetail(id) {
alert(id);
var windowID = '_detail'+id;
ColdFusion.Window.create(windowID,'Order Details','details.cfm?orderDetails='+id,{x:100,y:100,height:150,width:500,modal:false,closable:true,draggable:false,resizable:false,center:false,refreshOnShow:true}); ColdFusion.objectCache[getOrders].selectedRow=-1;
}
FYI, the cfwindow, simply contains code that pulls a query based upon the passed url parameter to populate a cfgrid within the cfwindow.
Comment 39 written by Clay on 29 September 2009, at 1:33 PM
Keep using the force!
Comment 40 written by Yousaf Riaz on 27 January 2010, at 4:00 PM
Comment 41 written by Raymond Camden on 27 January 2010, at 4:06 PM
[Add Comment] [Subscribe to Comments]