Updating a drop down based on an HTML Grid Selection

A user on cf-talk today asked if you could bind a drop down to an HTML grid. I tried it and got an error. The drop down expects a query or 2d array for it's source. Too bad. But - there is a solution. I blogged a few weeks ago about noting grid changes (Reacting to a grid row selection). This technique uses the CFAJAXPROXY tag to monitor the grid. In my previous blog entry, I just did an alert, but it's trivial to update a drop down as well. Consider the following example:

<cfajaxproxy bind="javascript:fixCat({entries.category})">

<script> function fixCat(c) { var dd = document.getElementById('mycat'); console.log(dd.options.length); for(var i=0; i<dd.options.length;i++) { if(dd.options[i].value==c) dd.selectedIndex=i; } } </script> <cfset q = queryNew("category,title")> <cfloop index="x" from="1" to="10"> <cfset queryAddRow(q)> <cfset rcat = listGetAt("Cat1,Cat2,Cat3", randRange(1,3))> <cfset querySetCell(q,"category", rcat)> <cfset querySetCell(q,"title", "Title #x#")> </cfloop>

<cfform name="test"> <cfgrid autowidth="true" name="entries" format="html" query="q" width="600" bindOnLoad="true"> <cfgridcolumn name="category" display="true">

<cfgridcolumn name="title" header="Title"> </cfgrid>

<cfinput type="text" name="thetitle" bind="{entries.title}"> <cfselect name="mycat" id="mycat"> <option value="Cat1">Cat1 <option value="Cat2">Cat2 <option value="Cat3">Cat3 </cfselect> </cfform>

So a good part of the code is my fake query and grid. You can pretty much ignore that. Note the first line uses cfajaxproxy with a bind attribute. This is what will fire and pass the proper column value to my function. I then just check the drop down option values and select it when I find a match.

In the grid - why did I have display="true"? Well normally this would be a hidden column, but I wanted to double check my work and ensure that the code was working. Not that I make mistakes of course.

Off Topic P.S.: Today I discovered "Apocalpso" by Mew. Dang what a good song. I've played it about 10 times now. Of course, every time I hear a really cool song - the first thing I want to do is try to play it in Guitar Hero II!

Archived Comments

Comment 1 by Gareth posted on 9/1/2007 at 3:13 AM

The console.log is for firebug, right? I think that will throw an error in IE if people copy and paste the code directly.

All the bind stuff is really nice though. I really need to download the dev edition locally and check it out more.

Comment 2 by Shawn Inman posted on 9/1/2007 at 4:10 AM

Thumbs up on the Mew comment. I first downloaded Apocalypso when it was the free single of the week long ago, and I totally fell in love with it. Rock on, Ray!

Comment 3 by todd sharp posted on 9/1/2007 at 5:14 AM

Gareth: You could have easily done a ColdFusion.Log.dump() too...

Comment 4 by Gareth posted on 9/1/2007 at 6:14 AM

Certainly. Just wanted to make sure there wasn't another reason for the console.log

Comment 5 by Raymond Camden posted on 9/1/2007 at 8:14 AM

@Gareth - yep - that was a mistake (me leaving the line in there).

Comment 6 by Will Swain posted on 9/1/2007 at 12:36 PM

Thanks Ray. Looks like that does just what I needed.

Comment 7 by Oliver posted on 9/14/2007 at 4:32 PM

Now try and get a pull down within a html cfgrid. there seems to be a bug with cfgridcolumn and valuesdisplay and value. Everything works swell, until you pick a pull down and the display switches to the value rather then the valuedisplay. when I did a submit, the submited form varibles got scrambled. Sad really every CFrelease I keep wanting to use the new UI functions, and they always seem to fail. For fun I tried dumping the entire <select></select function into the calling query, it almost worked but something inside cfgrid prevented selecting other selections

Comment 8 by M posted on 10/11/2007 at 2:10 AM

I'm having trouble updating the drop down when the form first loads. Works great otherwise. Any suggestions on how to get this to fire when it's first loaded?

Comment 9 by tim posted on 4/21/2008 at 7:32 PM

i did it this way since i'll have many dropdowns and want to use the same js function to select all of them. Works great. ajaxproxy works great too just thought this might be helpful.

<script type='text/javascript'>
var hasRun = false;
function selectDropDown(x,val) {
if(!hasRun) {
var dd = document.getElementById(x);
for(var i = 0; i < dd.length; i++){
if(dd.options[i].value == val){
dd.selectedIndex = i;
}
}
}
hasRun = true;
}
</script>

<cfinput type="hidden" name="categoryHiddenBind" value=""
bind="javascript:selectDropDown('CategoryID',
{grid.ComponentCatID})">
*Category:
<cfselect query="getCategories" name="CategoryID"
display="CategoryName" value="CategoryID" queryPosition="below">
<option value="0">-- Select a Category -- </option>
</cfselect>

Comment 10 by Ken Caldwell posted on 7/31/2009 at 5:29 AM

Ray,
You are doing a lot of work here for nothing.
As you can do the following
<cfselect name="mycat" bind="cfc:categories.getCategories({test:entries.category})" bindonload="true"></cfselect>

This then allows you to use the passed argument in your cfc. But note that the grid appears to pass a null value initially and the the selected value of the first row.

So, before I use it in my cfc I do a cfif and if the value is 'null' then I set the id value to zero.

I can supply and example if you need it.

Comment 11 by Raymond Camden posted on 7/31/2009 at 7:20 AM

I'm not so sure that it is a lot of work for nothing per se. Your method requires another HTTP call to get the data whereas mine would use the info already in the grid. I do think its an interesting alternative and it requires less client side code (although it would need more server side code).

Comment 12 by Ken Caldwell posted on 7/31/2009 at 8:20 AM

Ray,
I could not use your example as I needed to filter the dd by another column other than the two in the dd.

Ken

Comment 13 by James Lamar posted on 5/19/2010 at 10:21 PM

In response to what @Oliver wrote, could you share an example of using this inside the grid such as the case with a type="combobox"? I get the same thing he does where I can manually enter the values/valuesDisplay, but even then it will show the selected value rather than valuesDisplay. I'd like to use a query rather than manually code the dropdown.

Comment 14 by Michael Appenzellar posted on 10/1/2010 at 11:43 PM

Now, is there a way to have a dropdown be inside a grid column and have another dropdown inside another grid column and then the dropdowns relate? So the value of dropdown 1 determines the value of dropdown 2?

Comment 15 by Raymond Camden posted on 10/2/2010 at 6:49 PM

So I know that you can do a DD box in a grid in CF9. So you could have 2 columns both using DD boxes. I don't know if you can change one based on the other. Even if you could - afaik the values for the DD are hard coded. So if you changed the value in DD 1, then even if you can change DD2, you would just be picking one of the values already there. It's not like your typical State/City type thing.

Now - I'm sure you could do this completely if you had a full Ext Grid in play. So if you get the Grid object you may be able to do this w/ JS. I'm sure other grids would allow for it as well. I don't say this to imply cfgrid sucks, but that your options can be a bit limited sometimes with what you can do with it compared to building a grid with Ext, or jQuery, 100% from scratch (by scratch I mean a plugin of course ;).