I've had a simple CFGRID demo sitting in my local web server for a few months now and never got around to sharing it on the blog. Today I responded to user with another CFGRID question and figured it would be good to share them both in one example. (Plus, the code has been sitting in my test.cfm file all that time and I want to get rid of it. ;) So let's start with the first example - relating one cfgrid to another.

I've got two simple cfgrids tied to the cfartgallery database. The first cfgrid is bound to the Media database table:

<cfgrid bind="cfc:test.getMedia({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})" name="mediaGrid" format="html" width="400"> <cfgridcolumn name="mediaid" display="false"> <cfgridcolumn name="mediatype"> </cfgrid>

The CFC, test, has a basic query to grab the media info. Notice we have to support the 4 required arguments gridpage, pagesize, sortcolumn, and sortdirection, when binding with grids.

component {

remote struct function getMedia(page,size,col,dir) { var q = new com.adobe.coldfusion.query(); q.setDatasource("cfartgallery"); q.setSQL("select mediaid, mediatype from media"); return queryConvertForGrid(q.execute().getResult(),page,size); }

}

So far so good, right? Ok, how do I bind another grid to this one?

<cfgrid bind="cfc:test.getArt({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},{mediaGrid.mediaid})" name="artGrid" format="html" width="400" bindonload="false" > <cfgridcolumn name="artname"> <cfgridcolumn name="price"> </cfgrid>

I've taken a normal bound cfgrid, and simply appended additional arguments to the end of the required list. In this case, I've bound to the first grid's mediaid column. Now all I need is a CFC method that handles this:

remote struct function getArt(page,size,col,dir,media) { var q = new com.adobe.coldfusion.query(); q.setDatasource("cfartgallery"); q.setSQL("select artname, price, issold from art where mediaid = :mediaid"); q.addParam(name="mediaid",value="#arguments.media#",cfsqltype="cf_sql_integer"); return queryConvertForGrid(q.execute().getResult(),page,size); }

Pretty simple, right? I don't really make use of ColdFusion's Ajax UI stuff any more, but it certainly does a good job of simplifying things.

Now let's take it a step further. What if we wanted to bind a checkbox to a grid? Turns out - there isn't a simple way to do this. Binding a text box is simple enough. If we add the issold property to the grid (to "listen" to data in a grid, it has to be a grid column) we can then work with it:

<cfgrid bind="cfc:test.getArt({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection},{mediaGrid.mediaid})" name="artGrid" format="html" width="400" bindonload="false" > <cfgridcolumn name="artname"> <cfgridcolumn name="price"> <cfgridcolumn name="issold" display="false" > </cfgrid>

For my first test, I used a text field, just to ensure it was binding ok:

<cfinput type="text" name="issold" bind="{artGrid.issold}">

This worked, but wasn't the checkbox we wanted. What we really want is - bind to the grid's issold value and set or clear the checked attribute. cfinput does support a bindAttribute argument, but it only works with text fields, which seems truly odd. There's a simple enough workaround though. You can bind to a change in a grid by attaching it to a JavaScript function.

<cfajaxproxy bind="javascript:noteChange({artGrid.issold})">

This little gem here just says - when the grid changes, specifically the issold value, run a JavaScript function. We can then do:

<script> function noteChange(sold){ var b = false; if (sold == 1) { b = true; } document.getElementById("issoldcb").checked=b; } </script>

In case you're wondering, the logic there around sold was because it was being treated as a string.

If you want to test this, try the demo here: http://www.raymondcamden.com/demos/2012/jan/22/test.cfm