Earlier this week a user asked me to look into something odd with CF901's new multirowselect feature for cfgrid. If you haven't played with this yet, it is a way to enable multiple row selections in a grid. Unfortunately it doesn't quite work as advertised, but in this blog entry I'll tell you how to make it work.

First, let's start with a simple example so you can see what the attribute does when enabled.

<cfset q = queryNew("id,name")> <cfloop index="x" from="1" to="10"> <cfset queryAddRow(q)> <cfset querySetCell(q, "id", x)> <cfset querySetCell(q, "name", "Name #x#")> </cfloop>

<cfform name="mytest" method="post"> <cfgrid name="SelectStuff" query="q" format="html" width="400" height="250" multirowselect="true"></cfgrid> <cfinput type="submit" name="submit" value="Submit"> </cfform>

<cfdump var="#form#">

My code begins with a quick fake query on top. Next I've got a cfform with my grid inside. The only thing really interesting there is the multirowselect. I also added a quick dump of the form scope to the bottom. Let's take a look at how the grid is changed. I'll first show a picture with the option turned off, this is the default:

Now let's turn the option back on, as in the code above.

As you can see, there is a new column now with checkboxes. There is also a checkbox on top. Clicking that works as a Select All/Deselect All feature. So in theory, that should be it, right? Unfortunately, it completely doesn't work as shown above. If I click a few checkboxes and hit submit, I get this in the form scope.

Nothing. Ugh. So I pinged Adobe on this. Turns out - the real expectation for this feature was within Ajax-based applications. You can get the value just fine via JavaScript, but if you don't do this, nothing will be sent to the server. I've already filed a bug report on this.

So how can you make this work? The simplest solution is to use the getSelectedRows API:

obj = ColdFusion.Grid.getSelectedRows('SelectStuff');

This returns a struct of objects. How do you send that to the server? One option would be to turn into JSON:

jsonbj = ColdFusion.JSON.encode(obj);

However, this will give you a JSON representation of the entire row. You probably only want the ID values, right? Here is the code I came up:

var selected = ""; for(var i=0; i<obj.length; i++) { if(selected == "") selected = obj[i].ID; else selected += "," + obj[i].ID; } document.getElementById('selected').value = selected;

Basically - create a list of IDs from the object and assign it to a new form field, in this case, a hidden one. You can try this yourself via the demo link below, and I've pasted the entire completed template below.

<cfset q = queryNew("id,name")> <cfloop index="x" from="1" to="10"> <cfset queryAddRow(q)> <cfset querySetCell(q, "id", x)> <cfset querySetCell(q, "name", "Name #x#")> </cfloop>

<script> function fixMe() { obj = ColdFusion.Grid.getSelectedRows('SelectStuff'); var selected = ""; for(var i=0; i<obj.length; i++) { if(selected == "") selected = obj[i].ID; else selected += "," + obj[i].ID; } document.getElementById('selected').value = selected; return true; } </script>

<cfform name="mytest" method="post" onSubmit="return fixMe()"> <cfgrid name="SelectStuff" query="q" format="html" width="400" height="250" multirowselect="true"></cfgrid> <input type="hidden" name="selected" id="selected"> <cfinput type="submit" name="submit" value="Submit"> </cfform>

<cfdump var="#form#">