Selecting Multiple Default Items With ColdFusion 8 Ajax Controls
Ray just blogged about a technique that he and I worked together on to get ColdFusion 8 Ajax controls to have a default selected item. I started posting comments over there and decided to throw together a quick demo here to expand on it a bit. As Ray mentioned we started off building upon Ben's posts.
To add support for selecting multiple items I modifed the JavaScript to accept an array of items. I did have to use a bit of mysteriously undocumented code in this example - namingly the ColdFusion.JSON.decode() function (see this post for more on that).
Here is what the CFC looks like:
<cfset THIS.dsn="cfartgallery">
<!--- Get array of media types --->
<cffunction name="getMedia" access="remote" returnType="query">
<!--- Define variables --->
<cfset var data="">
<!--- Get data --->
<cfquery name="data" datasource="#THIS.dsn#">
SELECT mediaid, mediatype
FROM media
ORDER BY mediaid
</cfquery>
<cfreturn data>
</cffunction>
<!--- Get art by media type --->
<cffunction name="getArt" access="remote" returnType="query">
<cfargument name="mediaid" type="numeric" required="true">
<!--- Define variables --->
<cfset var data="">
<!--- Get data --->
<cfquery name="data" datasource="#THIS.dsn#">
SELECT artid, artname
FROM art
WHERE mediaid = #arguments.mediaid#
ORDER BY artname
</cfquery>
<cfreturn data>
</cffunction>
</cfcomponent>
Here's the modified code:
<script>
var imdone = false;
function test(x,val) {
if(!imdone) {
var dd = document.getElementById('mediaid');
valArr = ColdFusion.JSON.decode(val);
for(var i = 0; i < dd.length; i++){
//loop over the array of selectedItems for(var j = 0; j < valArr.length; j++){
if(dd.options[i].value == valArr[j]){
dd.options[i].selected = true;
}
}
}
imdone = true;
}
}
</script>
And the select modified to accomodate:
bind="cfc:art.getMedia()" size="4" multiple="true"
bindonload="true" value="mediaid" display="mediatype" />
So this works out - the first select item will now have items 1 and 2 selected by default (note that this is the 'mediaid' that I am passing to the cfc, not the selectedIndex). If you ran this out of the box with the CFC above you'd notice that the bind fails on the second select. This is because - first of all - the argument type is set as numeric. So changing the type to 'any' (or removing the type checking) is the first step. Now in the bind the first select will pass a comma seperated list of selected items to the cfc. Simple enough - just handle that in the query (using an 'in' clause) and voila. The second select will now return ALL art items related to all of the selected media types in the second select. Pretty cool!
Here is the modified getArt function:
<cfargument name="mediaid" type="any" required="true">
<!--- Define variables --->
<cfset var data="">
<!--- Get data --->
<cfquery name="data" datasource="#THIS.dsn#">
SELECT artid, artname
FROM art
WHERE mediaid in (#arguments.mediaid#)
ORDER BY artname
</cfquery>
<cfreturn data>
</cffunction>




Here's some info if your interested:
BigString (http://www.bigstring.com), the new free webmail program, offers revolutionary features. When you send mail from your BigString account, you are protected. BigString is like an automatic shredder for your email. You can self-destruct or change an email that's already been sent or read. Don't leave your messages sitting in peoples' inbox forever.
I tried updating the javascript by adding the same logic to the 2nd select but it doesn't work.
Thanks.
I have 2 related selects (lets stick with the "media" and "art" examples) but I need to pass in previosly selected values as defaults - esp the second "art" cfselect
but how?
I've created a .js file that "overrides" a function from coldfusion's cfajax.js library.
The new version of the function allows you to specify which options are selected as part of the array you return from your "bound" .cfc function.
See my site for details.
http://www.realitystorm.com/experiments/coldfusion...
<cfoutput query="Retailer">
<cfajaxproxy bind="javascript:test({category_id},#category_id#)">
...etc...
I've yet to work out how to pre-populate the subcategory drop-down. Help appreciated.