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
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.
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!
Gareth: You could have easily done a ColdFusion.Log.dump() too...
Certainly. Just wanted to make sure there wasn't another reason for the console.log
@Gareth - yep - that was a mistake (me leaving the line in there).
Thanks Ray. Looks like that does just what I needed.
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
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?
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>
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.
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).
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
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.
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?
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 ;).