Home » ColdFusion Ajax Tutorial 2: Related Selects
Many of us have built related select controls, forms with two (or more) drop down
Select Media Type:
Select Art:
The form contains two controls, one named “mediaid” and the other named “artid”.
“mediaid” is bound to cfc:art.getMedia(), and so to obtain the list of media types to populate the control, the client makes an asynchronous call to the getMedia method in art.cfc, and populates the list with the returned array. As we’d want this control to be automatically populated when the form loads, bindonload is set to “true", this way the getMedia() call is fired automatically at form load time.
“artid” is bound to the getArt method in art.cfc. This method requires that a mediaid be passed to it, and so {mediaid} is used so as to pass the currently selected value of control mediaid (the first ). Because these two controls are bound together, the second dependant on the first, ColdFusion automatically generates JavaScript code that forces artid to be repopulated with newly retrieved data whenever mediaid changes.
This example binds just two controls, but this mechanism can be used to relate as many controls as needed, and not just controls either.
164 responses to “ColdFusion Ajax Tutorial 2: Related Selects”
Wayne
With a good amount of help from Support I finally know how this works with separate XML results…from my previous post.
As was explained to me… the gist is to get the ID from the first dropdown into an array (a non XML object) so that it can be used as a value within the subsequent function for the subsequent dropdown.
My question is this: What actually gets passed from the first dropdown? In Ben’s example it’s the {mediaid} from the cfselect. I’d like to know if it’s truly an XML object or a number within an array…as it appears in the cfargument line.
Hello all, I have really found this tutorial useful. But I really need some help expanding it.
All I am doing is changing the dropdowns to multiple selects, so adding multiple="true" to the cfselects (and updating the cfc to handle the comma seperated list instead of single value – no problem). It seems to work great. Except by default nothing is selected. So, the second select doesnt populate (which is fine with me!). However, it throws an error executing the DB query (because the first value hasnt been selected yet). This is the message:
error:http: Error invoking CFC /AJAXTest/art.cfc : Error Executing Database Query.
When I select a media type, it works, it seems to be as expected, except I have to do something to stop this error. I cant figure out how to make a default selection, suppress the error, or tell the second selects bind to do nothing if mediaid is undefined. Please help!
I just tried setting bindonload=false on the first select box, and then it doesnt load when I go to the page. Should I use some other method to populate the first select box?
I had tried setting bindonload=false for the second select box but that did nothing. Any other thoughts?
Well, I think I found out that the error I was getting was in the query like it said, I just really didnt want to manipulate the default case, and wasnt sure how. I realized its just passing a null while nothing is selected. I can manipulate the query to say if mediaid GT 0 add WHERE mediaid IN (#arguments.mediaid#) and then change it to something else (like select nothing or everything).
Now the issue is if I select everything, the first select populates super fast, but the second is EXTREMELY slow. In my application modeling this example I have about 75 items to return for the second select, and I really don’t want it to take so long to load the page initially. Is my only choice to blank out the field? I haven’t even gotten to the third related select yet, which is even bigger and slower to load initially (unacceptable slow).
Any thoughts on the best way to optimize this? Why is it so slow, and can a <cfselct> with binding and multiple=true be given a default selection? It would be nice to just select the first in the list like a normal dropdown does.
I am trying to do the example that you provided, but for some reason this code never calls the CFC
cfselect name="mediaid" bind="cfc:art.getMedia()" bindonload="true" />
Has anyone ever seen this before? I tried calling it via cfinvoke and it works fine.
<cfselect name="firstselectname" bind="cfc:cfcfilepath.cfcfilename.cfcfirstfunctionname()" bindonload="true" value="ID_value" display="display_value" />
are you missing the path maybe? You are also missing your value and display values.
I just tried this and i still don’t see it even making the call to the CFC. Is there something in the Application.cfm or OnRequestEnd.cfm that will allow this to work.
<cfselect name="mediaid" bind="cfc:art.getMedia()" bindonload="true" value="mediaid" display="mediatype" />
Hi,
I’ve made this related select with start value, but I have a problem:
my star value is — seleziona città — and this character with accent never encode well….
How can I set the encoding on a output of component?
You can see this on http://www.agriturismoincampania.it/ on the right box…
Thank you
Can anyone make this faster when using multiple related cfselects? Not usable with 50 entries in the 2nd cfselect, and progressively gets worse with each additional bound cfselect.
Thanks for the quick reply; unfortunately does not pertain to my situation. I think the reality is binding multi related cfselects has significant performance issues. Works great for 1sy 2sy related cfselects, but should be avoided with "n" number of select items.
Well, what I did above was able to make it faster. I turned them into multiple=true selects. I have 3 selects, and while they were very slow initially, i had hundreds of entries for the second two depending on the combinations. By doing everything I can to limit the data until those combination are selected it is much faster.
To start, can you default to a generic entry at the top of your list so nothing is loaded until a selection is made?
Also, if you have database queries to get this data, do what you can to speed them up. Dont use SELECT * when you can use SELECT id,name.
Good luck, hope some of this helps.
Binding to a url has proven to be much faster… very cool.
<cfselect name="region_name"
bind="url:region_district_store.cfc?method=getRegion&returnFormat=json®ion_x=#region#"
bindonload="true" />
<cfselect name="district_name"
bind="url:region_district_store.cfc?method=getDistrict&returnFormat=json®ion_x={region_name.value}&district_x=#district#"
bindonload="false" />
<cfselect name="store_name"
bind="url:region_district_store.cfc?method=getStore&returnFormat=json®ion_x={region_name.value}&district_x={district_name.value}&store_x=#store#"
bindonload="false" />
@ Tim V…Thank you so much for your post. I’ve been banging my head for hours trying to speed this up. FF & Safari were running it in less than 2 seconds with my app (which had 4 cfselects using bind) and IE7 took about 40 seconds. Now IE7 takes <
Tried your art.cfc sample as is but cannot resolve the Error Executing Database Query error.
It seems to be finding my /includes/art.cfc file no problem but can’t run the query. I’m stuck without some help.
I found most of the posting here on CFSELECT is selecting the first select then populate the rest. While I have a situation which I need to populate all the cfselection onload. It seem easy, by setting "bindonload=true",but the hard part is while select anyone of the cfselects and populate the rest. I am pulling my hair but still could not figure out how to do. If only we could manage coldfusion tag "bindonload" in javascript then my job would be easier. So I can use onChange event at the selecting CFSELECT to turnoff the "bindonload" for the rest CFSELECTS. But I javascript does not see it. Could anyone help?
I incorporated this into my code back in the beginning of the year and a few days ago it stopped working in IE6 and IE7 – not in firefox though.
I have two related drop down boxes:
<cfselect name="code" bind="cfc:questdata.getcats()" bindonload="true" />
<cfselect name="name" bind="cfc:questdata.getoptions({code})" />
<cfinput type="submit" name="find" value="Find your quest now!">
I have not changed this code since I first put it up there and all of a sudden in IE the boxes are empty and I get this error ‘Coldfusion’ is undefined.
Has there been some change the to libraries? can someone suggest something? Help!
Dani, be advised, if you are using long lists (say over 100 lines) it can be a real bugger to wait for the drop
downs to populate.
I would recommend returning the data a a json object in the bind:
bind="url:#cfc_dirctory#/art.cfc?method=getMedia&returnFormat=json&mediaid=#mediaid#"
it makes the build time on the dropdowns lighting fast.
Hello community, I have another question about this feature.
I have in my form 3 cfselects. The second and third populate depending on whatever has been selected on the first one. So far so good.
This is for my "Add project" screen. Now, if I need to edit the project, I couldn’t figure out yet how to select on the cfselects the info from the database but providing still the functionality of the "related" selects. In other words, if I need to modify the information on the second cfselect, it will still show me the options based on what the first cfselect retrieved from the database.
Could someone help me? Ben? Ray? Anybody?
Thanks a lot.
Dani
To explain with the code:
<cfselect name="nfgCliID"
bind="cfc:collection.getCompany()"
bindonload="true">
<option selected><cfoutput query="myQuery">#myCompany#</cfoutput></option>
</cfselect>
</td>
Also if your select looks like:
Select nfgCliID, myCompany
then you shouldn’ need to use:
<option selected><cfoutput query="myQuery">#myCompany#</cfoutput></option>
Thank you Christopher, but I think I got lost.
What the cachedwithin will do? Also, in which of my queries should it go? I have the first query to select the company the second to select the contact at that company and the third to select the projects for that company. Thanks for all the help by the way.
I only use that exact function when querying tables that are updated frequently.
cachedWithin (optional) Timespan, using the CreateTimeSpan function. If original query date falls within the time span, cached query data is used. CreateTimeSpan defines a period from the present, back. Takes effect only if query caching is enabled in the Administrator.
To use cached data, the current query must use the same SQL statement, data source, query name, user name, and password.
Hi
I have problem of similar kind with the cfselect not working with bind attribute.
The bind attribute is working properly in localhost but when uploaded to server the bind attribute is not working properly. I have application.cfc in my application however i also user this line of code "<cfcontent type="text/html" reset="yes">" at starting inside the function in cfcomponent.
The strange thing which i observed is when commented the cfc completely then I dont see any error dislpaying which is unusal( where an error is expected in normal case). But In my localhost I can see an error as expected.
I am having trouble with the ‘onChange’ event firing.
I use a query in the cfselect so I can have a value selected, if in edit mode.
Also there is a CFGrid that uses the .value to populate itself. I am in CF8.
The cfselect :
<cfselect name="OID_SERVICE" query="Selectdata" value="OID" display="Service_CD" selected="0"
onChange="showServiceRatesGrid();">
</cfselect>
The ‘selected’ value will come from a query column when implemented for real.
I have also tried “javascript: showServiceRatesGrid()†with and without the semi colon.
The JS function, up in the <body> tag is :
<script language="JavaScript" type="text/javascript">
showServiceRatesGrid() {
alert("one");
if (document.getElementById("OID_SERVICE").selected.value == "0") {
document.getElementById("ServiceRatesGrid").style.display="none";
} else {
document.getElementById("ServiceRatesGrid").style.display="block";
}
}
</script>
I want it to only show the grid if a value other than 1 is selected.
The ‘alert’ never appears.
Any ideas?
Is there a way to refresh the first select box if a new value is added to the underlying database table via a pop-up form?
On my entry form (myentry.cfm), the first select box, "hostgenus" is filled with "genus" (ex. Crassostrea, Crypto, etc.), the related select
for "hostgenus" called "hostspecies" contains the genus and species for the chosen genus. For example, if "Crassostrea" is
selected from "hostgenus", then "hostspecies" shows a list like this: Crassostrea ariakensis, Crassostrea virginica, etc.)
If the desired "hostspecies" isn’t in the box, a new one can be added via a pop-up form (popup1.cfm). The popup1.cfm contains
a select box, "cbo_genus", that is populated with a list of genus, and there is a form field where the species can be added.
So if I want to add a new genus/species, I select the genus that I want from "cbo_genus" and then in type the new species
name in the form field.
After the popup1.cfm is submitted, it closes. My new genus/species appears beautifully on myentry.cfm in the "hostspecies" box.
My problem is this: in the popup1.cfm mentioned, if I don’t see a genus that I want in the "cbo_genus" box, I can open,
from popup1.cfm, another a pop-up form, popup2.cfm, that allows a new genus to be added. After popup2.cfm submits, the
new genus appear’s in popup1.cfm’s cbo_genus box. I then select my new genus from cbo_genus and type my new species in the form
field. But after I submit popup1.cfm, I do not see my new entry. Neither my new genus in "hostgenus" or the new genus/species
in "hostspecies".
All of this makes sense to me. Which is why I understand that I need a way to refresh "hostgenus". Help will be appreciated.
I am joining the fray. I’ve tried everything in the 133 or so comments that I understood and I’m still getting; "Bind failed, element not found: num". First select fills and the second doesn’t. I’m hoping I just need another set of eyes to point something out to me. I’m adding my cfc and calling form code. Good luck and thanks in advance.
<cfcomponent output="false">
<cfset THIS.dsn="BCC">
<!— Get array of divisions —>
<cffunction name="getDivisions" access="remote" returnType="array">
<!— Define variables —>
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!— Get divisions —>
<cfquery name="data" datasource="#THIS.dsn#">
select num, romNum + ‘- ‘ + title as displayed
from divisions
where num < 6
order by num
</cfquery>
<!— Convert results to array —>
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.num[i]>
<cfset result[i][2]=data.displayed[i]>
</cfloop>
<!— And return it —>
<cfreturn result>
</cffunction>
<!— Get program by num —>
<cffunction name="getPrograms" access="remote" returnType="array">
<cfargument name="num" type="numeric" required="true">
<!— Define variables —>
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!— Get data —>
<cfquery name="data" datasource="#THIS.dsn#">
SELECT ProgCode, title
FROM progDetails
WHERE division = #ARGUMENTS.num#
ORDER BY title
</cfquery>
<!— Convert results to array —>
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.ProgCode[i]>
<cfset result[i][2]=data.title[i]>
</cfloop>
<!— And return it —>
<cfreturn result>
</cffunction>
</cfcomponent>
<cfform>
<table>
<tr>
<td style="padding-right:4px">Select Division:</td>
<td><cfselect name="selDiv" id="division"
bind="cfc:progDetails.getDivisions()"
bindonload="true" /></td>
</tr>
<tr>
<td>Select Programs:</td>
<td style="padding-right:4px"><cfselect name="selProg"
bindonload="false"
<!—bind="{selDiv.selectedItem.data}"></cfselect>—>
bind="cfc:progDetails.getPrograms({num})" />
</td>
</tr>
</table>
</cfform>
I’m still having the same issues I had before with this. I’ve had to use JQuery to achieve the same result, but revisiting it again and I would like to get this fixed.
CF Version 8,0,1,195765 Standard.
The code is as per your example. Firebug shows the cfc being hit, but nothing is returned and no error shown.
If I call the function in the cfc directly, rather than bind to it, then I get a result no problem, so clearly something is amiss with the binding.
I’d really appreciate any ideas.
Thanks
I’m still having the same issues I had before with this. I’ve had to use JQuery to achieve the same result, but revisiting it again and I would like to get this fixed.
CF Version 8,0,1,195765 Standard.
The code is as per your example. Firebug shows the cfc being hit, but nothing is returned and no error shown.
If I call the function in the cfc directly, rather than bind to it, then I get a result no problem, so clearly something is amiss with the binding.
I’d really appreciate any ideas.
Thanks
I have similar problem. Do you have other .cfc files in the same cfc folder? Try to create another folder only containing the .cfc file for your binding use. It works for me. I know some coding in other related files will interfere with the binding, I have not figured out exactly what yet.
Good luck!
Hi Jainee,
Nope. It happens that this project only has one cfc. Access is set to remote, and there is nothing in the code that I can see that would prevent it from working. Very annoying.
There is this interesting line in the cf ajax debug window:
window:global: _31c is null (http://*********/******/scripts/ajax/package/cfajax.js, line 1264)
I’m getting an "element var_proposal undefined" error that I cannot figure out! My select boxes look like this:
<cfselect name="cbo_status"
bind="cfc:proposal_status_cfc.getStatus()"
bindonload="true"
display="prop_status"
id="prop_status"
/>
<cfselect name="cbo_proposal"
bind="cfc:proposal_status_cfc.getProposal({cbo_status})"
value="prop_number"
size="3"
/>
Then in my cfc, in the function getStatus, I "select distinct prop_status from proposal" then in the function getProp I have a cfargument=var_proposal. I’b be glad to post all of the cfc’s code, but I didn’t want to clog the blog.
I’m getting an "element var_proposal undefined" error that I cannot figure out! My select boxes look like this:
<cfselect name="cbo_status"
bind="cfc:proposal_status_cfc.getStatus()"
bindonload="true"
display="prop_status"
id="prop_status"
/>
<cfselect name="cbo_proposal"
bind="cfc:proposal_status_cfc.getProposal({cbo_status})"
value="prop_number"
size="3"
/>
Then in my cfc, in the function getStatus, I "select distinct prop_status from proposal" then in the function getProp I have a cfargument=var_proposal. I’b be glad to post all of the cfc’s code, but I didn’t want to clog the blog.
I’m getting an "element var_proposal undefined" error that I cannot figure out! My select boxes look like this:
<cfselect name="cbo_status"
bind="cfc:proposal_status_cfc.getStatus()"
bindonload="true"
display="prop_status"
id="prop_status"
/>
<cfselect name="cbo_proposal"
bind="cfc:proposal_status_cfc.getProposal({cbo_status})"
value="prop_number"
size="3"
/>
Then in my cfc, in the function getStatus, I "select distinct prop_status from proposal" then in the function getProp I have a cfargument=var_proposal. I’b be glad to post all of the cfc’s code, but I didn’t want to clog the blog.
Ben,
I have implemented your example in my code and it is working well. My problem comes when I call the same form for edit. The fields are always populated BindOnLoad. I cannot figure out how to show the value from the data base, like having selected in html form. Is this not possible with this process. Do I need separate code to do the update?
Sorry for the NOOB question. I have copied the cfcomponent into a file and called it AJAX.cfc.
I then copied the form information into a file called AJAX.cfm. I saved them both to the
same folder. But when I run AJAX.cfm, I get an error that reads:
"The specified CFC art could not be found"
What am I missing?
I really need help with my dropdown menus with bind. I am getting the error "Bind failed, element not found: T_categories_ID"
The first menu shows up well, the second is empty. here’s the code. I must be missing something:-) And Yes,both category and subcategory are in 1 table, I am working on a CMS developed by someone else….
CFC:
<cfcomponent output="false">
<cfset THIS.dsn="#request.dba#">
<!— Get array of media types —>
<cffunction name="getcategories" access="remote" returnType="array">
<!— Define variables —>
<cfset var getcategories="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!— Get data —>
<cfquery name="sel_categories" datasource="#request.dba#">
SELECT
T_categories_ID,
T_categories_name as categoryname
FROM
T_categories
WHERE
T_categories_ID > 0
AND
T_categories_subcat_ID = 0
AND
T_categories_active = 1
AND
T_categories_partnerID = #session.partnerid#
ORDER BY T_categories_name ASC
</cfquery>
<!— Convert results to array —>
<cfloop index="i" from="1" to="#sel_categories.RecordCount#">
<cfset result[i][1]=sel_categories.T_categories_ID[i]>
<cfset result[i][2]=sel_categories.categoryname[i]>
</cfloop>
<!— And return it —>
<cfreturn result>
</cffunction>
<!— Get art by media type —>
<cffunction name="getsubcategories" access="remote" returnType="array">
<cfargument name="T_categories_ID" type="numeric" required="true">
<!— Define variables —>
<cfset var getsubcategories="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<!— Get data —>
<cfquery name="sel_sub_categories" datasource="#request.dba#">
SELECT DISTINCT
T_categories_subcat_ID,
T_categories_subcat_name as subcatname
FROM
T_categories
WHERE
T_CATEGORIES_SUBCAT_ID = #ARGUMENTS.T_categories_ID#
ORDER BY
subcatname ASC
</cfquery>
<!— Convert results to array —>
<cfloop index="i" from="1" to="#sel_sub_categories.RecordCount#">
<cfset result[i][1]=sel_sub_categories.T_CATEGORIES_SUBCAT_ID[i]>
<cfset result[i][2]=sel_sub_categories.subcatname[i]>
</cfloop>
<!— And return it —>
<cfreturn result>
</cffunction>
</cfcomponent>
__________________________
CFM:
<cfselect name="categories"
bind="cfc:cfc.categories.getcategories()"
bindonload="true" />
<cfselect name="subcategories"
bind="cfc:cfc.categories.getsubcategories({T_categories_ID})" />
_________________
Hi-
When i executed this code on my local system, it executed fine, but when I
uploaded to http://www.lasanisarkar.org/bait/form.cfm and executed it does not give any error except
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.3; .NET4.0C; .NET4.0E)
Timestamp: Tue, 19 Jul 2011 06:02:37 UTC
Message: Exception thrown and not caught
Line: 798
Char: 1
Code: 0
URI: http://www.lasanisarkar.org/CFIDE/scripts/ajax/package/cfajax.js
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept All”, you consent to the use of ALL the cookies. However, you may visit "Cookie Settings" to provide a controlled consent.
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
Cookie
Duration
Description
cookielawinfo-checkbox-analytics
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional
11 months
The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy
11 months
The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Leave a Reply