AdobeStock_455007340

ColdFusion Ajax Tutorial 2: Related Selects

Many of us have built related select controls, forms with two (or more) drop down control) and the second containing the display text. (For now, this two dimensional array is the format required by ).
Now for the form itself:

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&quot, 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”

  1. PISSED OFF Avatar
    PISSED OFF

    I can’t believe it is still an issue with using an Application.cfc …
    No application.cfc and this sample works perfect.
    Add an Application.cfc and it goes to crap..
    Why pray tell has Adobe not addressed this issue?
    This has been a problem since 5/31/07..
    Holly crap, do I need to look a for a different programming language, cus if adobe is not working on issues like this after 4 years…… I have to wonder are they working on CF X anymore or will this programming language just get shoved to the side,
    And I should start learning @#$#@$#*#$%& PHP?
    It would behoove someone to reply to this comment, as I can’t believe the laziness I am seeing with CF issues…

  2. ion Avatar
    ion

    in cf9, this example doesn’t work very well, in fact, i was only able to make it work having a cfselect and a cfgrid, but not with 2 cfselects. on the other hand, it works perfect without arrays:
    <pre>
    <cfcomponent>
    <!— Get array of groups —>
    <cffunction name="getGroups" access="remote" returnType="query">
    <cfset var groupData = "">
    <!— Get data —>
    <cfquery name="groupData" datasource="myDSN">
    SELECT group_id, group_name
    FROM myTable
    </cfquery>
    <!— And return it —>
    <cfreturn groupData>
    </cffunction>
    <cffunction name="getApps" access="remote" returnType="query">
    <cfargument name="group_id" required="true">
    <cfset var appData = "">
    <cfquery name="appData" datasource="myDSN">
    SELECT app_id, app_display_name
    FROM myOtherTable
    WHERE group_id = #arguments.group_id#
    </cfquery>
    <cfreturn appData>
    </cffunction>
    </cfcomponent>
    <!————————————————————————>
    <cfform>
    <cfselect name="groups" bind="cfc:selects.getGroups()" bindonload="true" value="group_id" display="group_name" selected="group_id" />
    <p>
    <cfselect name="apps" bind="cfc:selects.getApps({getGroups})" bindonload="false" value="app_id" display="app_display_name" selected="app_id" />
    </cfform>
    </pre>

  3. Cathy White Avatar
    Cathy White

    You may find yourself here looking for help with a "bind failed" error, just as I did a couple of weeks ago. Unfortunately for me, the quick tips I found here and elsewhere didn’t solve my exact problem. Some code I didn’t write that had been "working" for over a year starting producing an avalanche of "bind failed" errors seemingly out of the blue, but only in IE 9 and nowhere else. This in itself is a clue, and if this is your problem, I recommend the following:
    I copied the code into a test page and began by eliminating all of the extraneous javascript and formatting in the template of the page. The error still occurred, which ruled out any of that code. Then I began methodically eliminating code until I was able to isolate the problem: improper HTML structure was causing the error. How imperfect was it? It was an unclosed <p> tag. I spent upwards of 5 hours on this problem only to fix it with 3 keystrokes. Imagine the four-letter words I mentally edited out of that last sentence.
    It appears that the smallest deviation from proper HTML structure can cause this problem in IE 9. If I had started with methodical instead of looking for a quick fix, I could have saved some hours, but maybe you will see this and save yourself some time. Alas, it is too late for me.

  4. Alex Zamora Avatar
    Alex Zamora

    How can I preserv the select value when there are errors and you click the back browser button and avoid to reset the cfselect?

  5. Allen Avatar
    Allen

    Ben,
    I found this is very helpful since I’m not savvy with Javascript but I need the value of my second dropdown be able to do a little bit more thn just showing
    a value related to the first drop down.
    For example:
    The first drop down is listing amount of money such as $10,$20,$30,$40, etc
    The second drop down will list the related fees: $2,$5,$10,$20,etc
    In certain cases I need to apply dicount to the fee so I need to past 2 values from my second drop down this way when a discount exist for this user
    the fee listed on the drop down should show discounted fee.
    I tried this to my second drop down but it did not work:
    <cfselect name="OurFee" bind="cfc:cfcomponents.mycomponent.getFees({FeeID,Diskon})" class="inputSelect" />
    On the component side I did:
    <CFIF arguments.Diskon LTE 10>
    <cfquery name="datafee" datasource="MyDSN">
    SELECT OurFee
    FROM tblFeeLookUp
    WHERE FeeID = <cfqueryparam cfsqltype="cf_sql_numeric" value="#ARGUMENTS.FeeID#">
    </cfquery>
    <CFELSE>
    <cfquery name="datafee" datasource="MyDSN">
    SELECT (OurFee – #arguments.Diskon#) AS OurFee
    FROM tblFeeLookUp
    WHERE FeeID = <cfqueryparam cfsqltype="cf_sql_numeric" value="#ARGUMENTS.FeeID#">
    </cfquery>
    </CFIF>
    Can I get some help on how to be able to do something like this?

  6. Derek Versteegen Avatar
    Derek Versteegen

    [sign] So I’ve been reading this post up and down and I can’t seem to find the answer to my issue – many close issues but not quite exactly what I am running into.
    So, the short of it is my first select drop box works successfully – bind, function, query, array, to drop box. On page load, the second drop box doesn’t have any options. When an option from the first drop box is selected, the second one does not update.
    All my functions work – when I hard code and invoke mt CFC at the top of the page, passing in a value from what would be in the second drop box, I get a result. But, the bind in the second select doesn’t seem to either running the update or passing a value in.
    There seems to be similar issues here in the past but I can’t seem to find a resolution. I’m running CF 9,0,0,251028 and the following code:
    First Select:
    <cfselect name="resource_unit" id="resource_unit" bind="cfc:/cfc/Practitioners.aryGetResourceUnits()" bindonload="true" tabindex="4" />
    Second Select
    <cfselect name="abbreviation" id="abbreviation" bind="cfc:/cfc/Practitioners.aryGetPractitioners({resource_unit})" bindonload="false" tabindex="5" />
    I can post more code if needed, but all the functions in the CFC work when invoked on the form page.
    Eventually, I want to add this so there is ultimately a third field updated with the selection from the second drop box.
    <cfinput type="text" name="employee_name" id="employee_name" value="" size="35" tabindex="6" bind="cfc:/cfc/Practitioners.aryGetPractitioner({abbreviation})" bindonload="false" />
    Any help would be greatly appreciated.

  7. Derek Versteegen Avatar
    Derek Versteegen

    Ok – appending my post with an interesting behavior. I added an option to the <cfselect> tag and on page load the options I hard coded appear then are refreshed and removed. The first select drop box successfully populates with the correct options from the database call (the one I hard coded is removed from the options). The value I hard coded in the second drop box appears and then quickly refreshes and is removed and there are no options replaced. Which is fine since it is supposed to be dependent on the first select. But what is interesting is that the third text input field, for that brief moment, correctly grabs the second field value and looks it up to get the value I am ultimate after.
    This confirms that I’m not having a lot of the issues discussed here. But I can figure out why the other call backs are not triggered on change. Any ideas?
    Unit:<br />
    <cfselect name="resource_unit" id="resource_unit" bind="cfc:/cfc/Practitioners.aryGetResourceUnits()" bindonload="true" tabindex="4"><option value="PMRBG">PMRBG</option></cfselect><br />
    Abbreviation:<br />
    <cfselect name="abbreviation" id="abbreviation" bind="cfc:/cfc/Practitioners.aryGetPractitioners({resource_unit})" bindonload="true" tabindex="5"><option value="GAJOMAGE">GAJOMAGE</option></cfselect><br />
    Employee<br />
    <cfinput type="text" name="employee_name" id="employee_name" bind="cfc:/cfc/Practitioners.aryGetPractitioner({abbreviation})" value="" size="35" tabindex="6" bindonload="true" /><br />
    Functionally, the user selects a unit, which updates the Abbreviation list with a smaller list. When the user selects the abbreviation, it pulls the employee full name and puts it into the text input field.

  8. TJ Avatar
    TJ

    This tutorial is great, I was able to create 3 drop down selection for countries then states then cities.
    They work except when my users are accessing them from iPhone and google chrome they errors out!!!!!
    It says: Bind failed, element not found: CountryId [Enable debugging by adding ‘cfdebug’ to your url parameters to see more information]
    Not sure why this is happening because the code is not depend on the browser, how come CF can’t handle this? not sure how can I fix this situation because in other browsers, such as, IE and Mozilla, they work just fine!

  9. Jay Smith Avatar
    Jay Smith

    For some reason, if you have css on the same page, no data will appear in the dropdown.

  10. Tjenko Avatar
    Tjenko

    Hi Ben!
    I found this posting very helpful. I did it in one of my registration form and it was working beautifully.
    But when I need the same functionality for other form within this same application, the functionality doen’t work.
    The error message keep saying bind failed because CountryId is not passed.
    I copied and pasted the cfselects from the registration form to this other form and nothing is changed.
    Logically the bind on cfselect should call the same component, am I right?

  11. Alan Mackenzie Avatar
    Alan Mackenzie

    Hi Ben
    I love your concise code!
    This connected select box trick would be magic but I’m missing something!
    The first select works and triggers on the first onchange. The second function works if I invoke the component and manually populate the select with the data from the invoked function. However, the second select with the bind leaves me an empty box everytime.
    Also the onchange doesn’t seem to fire a second time.
    I’ve tried without the onchange and I’m getting nothingCould you help an old man out.
    Thanks terribly
    Alan (

  12. Juan Chavez Avatar
    Juan Chavez

    Hi, my name is Juan Chaves, I´m from Colombia, I tried the example and it went well, but add a third select and it did not work. Can you help me?

  13. Monique Boea Avatar
    Monique Boea

    Please assist
    I am getting the following error:
    Bind failed, element not found: catID [Enable debugging by adding ‘cfdebug’ to your URL parameters to see more information]
    Here is my form:
    <cfform>
    <table>
    <tr>
    <td>Select Media Type:</td>
    <td><cfselect name="cat1"
    bind="cfc:business.getBizCats1()"
    bindonload="true" /></td>
    </tr>
    <tr>
    <td>Select Art:</td>
    <td><cfselect name="cat1"
    bind="cfc:business.getBizCats2({catID})" /></td>
    </tr>
    </table>
    </cfform>
    Here is Method 1
    <cffunction name="getBizCats1" access="remote" returnType="array">
    <!— Define variables —>
    <cfset var data="">
    <cfset var result=ArrayNew(2)>
    <cfset var i=0>
    <!— Get data —>
    <cfquery name="data" datasource="#request.dsn#">
    select catID, category from category1
    where active = 1
    order by category
    </cfquery>
    <!— Convert results to array —>
    <cfloop index="i" from="1" to="#data.RecordCount#">
    <cfset result[i][1]=data.catID[i]>
    <cfset result[i][2]=data.category[i]>
    </cfloop>
    <!— And return it —>
    <cfreturn result>
    </cffunction>
    Here is Method 2
    <cffunction name="getBizCats2" access="remote" returnType="array">
    <cfargument name="catID" type="numeric" required="true">
    <!— Define variables —>
    <cfset var data="">
    <cfset var result=ArrayNew(2)>
    <cfset var i=0>
    <!— Get data —>
    <cfquery name="data" datasource="#request.dsn#">
    select catID, category from subCats1
    where active = 1
    and parentID = #arguments.catID#
    order by category
    </cfquery>
    <!— Convert results to array —>
    <cfloop index="i" from="1" to="#data.RecordCount#">
    <cfset result[i][1]=data.catID[i]>
    <cfset result[i][2]=data.category[i]>
    </cfloop>
    <!— And return it —>
    <cfreturn result>
    </cffunction>

  14. Wedding Receptions Melbourne Avatar
    Wedding Receptions Melbourne

    Thanks for the tip, seems like a few people are having difficulty with this application. I will give it a go and will be back if i need some help 🙂

Leave a Reply