SwitchedOnMedia
asked on
ColdFusion + Javascript - 2 Dynamic Drop Down Boxes
Hi,
I have two tables, one is countries and the other is counties.
I need the first drop down box to list all the countries, which it does :) The second one needs to be dynamically populated depending on the results of the first one. Thing is I want to do it without a page reload and just cant get it to work :(
<cfquery NAME="pull_country" DATASOURCE="#application.a ppdsn#">
SELECT country_id, country
FROM countries
ORDER BY country
</cfquery>
<cfquery NAME="pull_locations" DATASOURCE="#application.a ppdsn#">
SELECT county_id, county
FROM counties
ORDER BY county
</cfquery>
<select name="country" class="formobjects" id="location">
<option value="0">Please Select</option>
<cfoutput QUERY="pull_country">
<option value="#country_id#">#coun try#</opti on>
</cfoutput>
</select>
Any suggestions?
I have two tables, one is countries and the other is counties.
I need the first drop down box to list all the countries, which it does :) The second one needs to be dynamically populated depending on the results of the first one. Thing is I want to do it without a page reload and just cant get it to work :(
<cfquery NAME="pull_country" DATASOURCE="#application.a
SELECT country_id, country
FROM countries
ORDER BY country
</cfquery>
<cfquery NAME="pull_locations" DATASOURCE="#application.a
SELECT county_id, county
FROM counties
ORDER BY county
</cfquery>
<select name="country" class="formobjects" id="location">
<option value="0">Please Select</option>
<cfoutput QUERY="pull_country">
<option value="#country_id#">#coun
</cfoutput>
</select>
Any suggestions?
Here is another EE topic with the same topic in the coldfusin forum.
https://www.experts-exchange.com/questions/21536325/dynamic-drop-down-without-reloading.html
https://www.experts-exchange.com/questions/21536325/dynamic-drop-down-without-reloading.html
ASKER
Urgh, they are all messy and lead on to about 3 other posts. Is there actually a post with the code in to do it in ColdFusion anywherE?
Sorry, the CF Link actually has links to three methods. None of these are trivial.
Here is the Javascript method:
https://www.experts-exchange.com/questions/21268362/Two-Selects-Related.html
--- it actually has links to CF custom tag code also that should simplify this, but I didn't dig into it...
Here is a link to a method drawn up by mrichmon that shows how to submit queries in the background to dynamically change the lists
https://www.experts-exchange.com/questions/20936125/How-to-use-Javascript-to-submit-page-in-background-that-queries-database-and-pulls-info-to-fill-in-the-remaing-form.html
The last method that is mentioned is to use CFAJAX, but they don't really provide details on how to do this specifically.
http://www.indiankey.com/cfajax/
I believe it is related to this method. http://www.indiankey.com/cfajax/examples/list.htm
What you are wanting is not trivial and is going to take a lot of code. It doen't make sense to try and paste all that code into another link and the best that is going to happen is for someone just to copy code from one of these other links...
Here is the Javascript method:
https://www.experts-exchange.com/questions/21268362/Two-Selects-Related.html
--- it actually has links to CF custom tag code also that should simplify this, but I didn't dig into it...
Here is a link to a method drawn up by mrichmon that shows how to submit queries in the background to dynamically change the lists
https://www.experts-exchange.com/questions/20936125/How-to-use-Javascript-to-submit-page-in-background-that-queries-database-and-pulls-info-to-fill-in-the-remaing-form.html
The last method that is mentioned is to use CFAJAX, but they don't really provide details on how to do this specifically.
http://www.indiankey.com/cfajax/
I believe it is related to this method. http://www.indiankey.com/cfajax/examples/list.htm
What you are wanting is not trivial and is going to take a lot of code. It doen't make sense to try and paste all that code into another link and the best that is going to happen is for someone just to copy code from one of these other links...
I wrote this a while ago so it's not pretty, but it got the job done. I modified it a little to try and fit your request so forgive any typos :-)
<cfset CountyQry = QueryNew("CountyID,County_ name,Count ryID","Int eger,varch ar,integer ")>
<cfoutput query="counties">
<CFSET QueryAddRow(CountyQry,coun ties.curre ntrow)>
<Cfset QuerySetCell(CountyQry,"Co untyID",co unties.ID) >
<Cfset QuerySetCell(CountyQry,"Co unty_name" ,counties. NAme)>
<Cfset QuerySetCell(CountyQry,"Co untryID",c ounties.Co untryID)>
</cfoutput>
<script type="text/javascript">
function chgcounty(SelCountry){
var SelCounty;
var SelCountry;
SelCounty = document.myformname.counti es;
<cfloop query="pull_country">
if(SelCountry == "#pull_country.country_id# "){
SelCounty.options.length = countyQry.recordcount#+1;
<Cfquery dbtype="query" name="cnty">
SELECT CountyID,County_name,Count ryID
FROM CountyQry
WHERE CountryID = #pull_country.country_id#
ORDER BY County_Name
</CFQUERY>
<cfloop query="cnty">
SelCounty.options[cnty.cur rentrow] = new Option("#cnty.county_name# ","#cnty.C ountyID#") ;
</cfloop>
}
</cfloop>
}
</script>
<select name="countries" onchange="chgcounty(this.o ptions[thi s.selected Index].val ue">
<cfloop query="pull_country">
<option value="#pull_country.id#"> #pull_coun try.Countr y_Name#
</cfloop>
</select>
<select name="counties">
<option value="">
</select>
I took some liberties, like assuming your County DB table has the country ID, assuming the name of your FORM, etc...
May need a little configuring on your side but should help.
Good luck
<cfset CountyQry = QueryNew("CountyID,County_
<cfoutput query="counties">
<CFSET QueryAddRow(CountyQry,coun
<Cfset QuerySetCell(CountyQry,"Co
<Cfset QuerySetCell(CountyQry,"Co
<Cfset QuerySetCell(CountyQry,"Co
</cfoutput>
<script type="text/javascript">
function chgcounty(SelCountry){
var SelCounty;
var SelCountry;
SelCounty = document.myformname.counti
<cfloop query="pull_country">
if(SelCountry == "#pull_country.country_id#
SelCounty.options.length = countyQry.recordcount#+1;
<Cfquery dbtype="query" name="cnty">
SELECT CountyID,County_name,Count
FROM CountyQry
WHERE CountryID = #pull_country.country_id#
ORDER BY County_Name
</CFQUERY>
<cfloop query="cnty">
SelCounty.options[cnty.cur
</cfloop>
}
</cfloop>
}
</script>
<select name="countries" onchange="chgcounty(this.o
<cfloop query="pull_country">
<option value="#pull_country.id#">
</cfloop>
</select>
<select name="counties">
<option value="">
</select>
I took some liberties, like assuming your County DB table has the country ID, assuming the name of your FORM, etc...
May need a little configuring on your side but should help.
Good luck
Oops, just noticed my own typos...
First, the whole of the JAvaScript should be in a set of CFOUTPUT tags and this line:
SelCounty.options[cnty.cur rentrow] = new Option("#cnty.county_name# ","#cnty.C ountyID#") ;
should be:
SelCounty.options[#cnty.cu rrentrow#] = new Option("#cnty.county_name# ","#cnty.C ountyID#") ;
Good luck
First, the whole of the JAvaScript should be in a set of CFOUTPUT tags and this line:
SelCounty.options[cnty.cur
should be:
SelCounty.options[#cnty.cu
Good luck
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I'm trying to use your code but I get this error ...
Error Occurred While Processing Request
There is no column in the query object.
Here's the code:
<cfquery NAME="pull_country" DATASOURCE="#application.a ppdsn#">
SELECT country_id, country
FROM countries
ORDER BY country
</cfquery>
<cfquery NAME="pull_locations" DATASOURCE="#application.a ppdsn#">
SELECT county_id, county, country_id
FROM counties
ORDER BY county
</cfquery>
<cfset CountyQry = QueryNew("county_id,county ,country_i d","Intege r,varchar, integer")>
<cfoutput query="pull_locations">
<CFSET QueryAddRow(CountyQry,pull _locations .currentro w)>
<Cfset QuerySetCell(CountyQry,"Co untyID", county_id)>
<Cfset QuerySetCell(CountyQry,"Co unty_name" , county)>
<Cfset QuerySetCell(CountyQry,"Co untryID", country_id)>
</cfoutput>
<CFOUTPUT>
<script type="text/javascript">
function chgcounty(SelCountry){
var SelCounty;
var SelCountry;
SelCounty = document.myformname.counti es;
<cfloop query="pull_country">
if(SelCountry == "#pull_country.country_id# "){
SelCounty.options.length = #countyQry.recordcount#+1;
<Cfquery dbtype="query" name="cnty">
SELECT CountyID,County_name,Count ryID
FROM CountyQry
WHERE CountryID = #pull_country.country_id#
ORDER BY County_Name
</CFQUERY>
<cfloop query="cnty">
SelCounty.options[#cnty.cu rrentrow#] = new Option("#cnty.county_name# ","#cnty.C ountyID#") ;
</cfloop>
}
</cfloop>
}
</script>
<select name="countries" onchange="chgcounty(this.o ptions[thi s.selected Index].val ue">
<cfloop query="pull_country">
<option value="#pull_country.count ry_id#">#p ull_countr y.country# </option>
</cfloop>
</select>
<select name="counties">
<option value="">
</select>
</CFOUTPUT>
Error Occurred While Processing Request
There is no column in the query object.
Here's the code:
<cfquery NAME="pull_country" DATASOURCE="#application.a
SELECT country_id, country
FROM countries
ORDER BY country
</cfquery>
<cfquery NAME="pull_locations" DATASOURCE="#application.a
SELECT county_id, county, country_id
FROM counties
ORDER BY county
</cfquery>
<cfset CountyQry = QueryNew("county_id,county
<cfoutput query="pull_locations">
<CFSET QueryAddRow(CountyQry,pull
<Cfset QuerySetCell(CountyQry,"Co
<Cfset QuerySetCell(CountyQry,"Co
<Cfset QuerySetCell(CountyQry,"Co
</cfoutput>
<CFOUTPUT>
<script type="text/javascript">
function chgcounty(SelCountry){
var SelCounty;
var SelCountry;
SelCounty = document.myformname.counti
<cfloop query="pull_country">
if(SelCountry == "#pull_country.country_id#
SelCounty.options.length = #countyQry.recordcount#+1;
<Cfquery dbtype="query" name="cnty">
SELECT CountyID,County_name,Count
FROM CountyQry
WHERE CountryID = #pull_country.country_id#
ORDER BY County_Name
</CFQUERY>
<cfloop query="cnty">
SelCounty.options[#cnty.cu
</cfloop>
}
</cfloop>
}
</script>
<select name="countries" onchange="chgcounty(this.o
<cfloop query="pull_country">
<option value="#pull_country.count
</cfloop>
</select>
<select name="counties">
<option value="">
</select>
</CFOUTPUT>
Take a look at the tag that mmc98dl1 suggests - Nate Weiss's two selects related is a very clean simple solution to this problem.
All you need do is write a JOINed query of your two tables, suitably GROUPed and pass it into Nate's tag. The attributes on the tag allow you to simply chose which type of select you need as well as any other details you need to set for the selects.
If you want to write this yourself, use the CFWDDX tag to get from query from CF into an array in JS.
This JS function should help you populate any given select.
<script language='JavaScript' type="text/javascript">
function fillnextdropdown(default_v alue,defau lt_text,se lected_val ue,formnam e,fieldnam e,querynam e,ParentID ,ChildID,d spColumn){
// with == in the form
with (eval("document."+formname )){
if (selected_value != 0) {
// If a real selection has been made
// Set up the defaults and clear the Activity Year Options
NewOpt = new Option;
var OptionCount = 0;
thisField = eval(fieldname);
thisQuery = eval(queryname);
thisParentIDCol = eval("thisQuery."+ParentID );
thisChildIDCol = eval("thisQuery."+ChildID) ;
thisdspColumn = eval("thisQuery."+dspColum n);
RowCount = thisParentIDCol.length;
thisField.options.length = 0;
// Add in a new top option
NewOpt.value = 0;
NewOpt.text = default_text;
thisField.options[OptionCo unt] = NewOpt;
// Now loop through the query we converted to a couple of arrays and output the appropriate options
for (var i = 0; i < RowCount; i++){
if (thisParentIDCol[i] == selected_value){
OptionCount++;
NewOpt = new Option;
NewOpt.value = thisChildIDCol[i];
NewOpt.text = thisdspColumn[i];
thisField.options[OptionCo unt] = NewOpt;
if (NewOpt.value == default_value)
thisField.selectedIndex = OptionCount;
}
}
}
}
}
</script>
Here is an example of a call of this function.
<select name="SubGroupID" class="formstyleblue" onchange="fillnextdropdown (<cfoutput >#attribut es.SubGrou pID#</cfou tput>,'Sel ect an email template >>',this[this.selectedInde x].value,' MassMailFo rm','Templ ateID','su bgrouptemp lates','su bgroupid', 'templatei d','templa tetitle')" >
<option value="0" class="bodytext">Select a Template Subscription Group >></option>
<cfoutput query="SubGroupTemplates" group="SubGroupID">
<option value="#SubGroupTemplates. SubGroupID #" class="bodytext">#SubGroup Templates. Title#</op tion>
</cfoutput>
</select>
<select name="TemplateID" class="formstyleblue">
<option value="0">Select a Subscription Group from the list above</option>
</select>
These lines need to be included in the page to allow CFWDDX to create the JS array from the query for this example:
<script language='JavaScript' src='/cfide/scripts/wddx.j s' type="text/javascript"></s cript>
<script language="JavaScript" type="text/javascript">
<cfwddx action="cfml2js" input="#SubGroupTemplates# " toplevelvariable="subgroup templates" >
</script>
And this is the query that is used to populate the first select and the JS array
<cfquery name="SubGroupTemplates" datasource="#request.dsn#" >
SELECT E.SubGroupID, E.Title, ET.TemplateID, CONCAT(ET.TemplateTitle,' (',ET.TemplateType,')') AS TemplateTitle
FROM EmailSubGroup E
INNER JOIN EmailTemplate ET ON E.SubGroupID=ET.SubGroupID
ORDER BY E.Title, ET.TemplateTitle
</cfquery>
All you need do is write a JOINed query of your two tables, suitably GROUPed and pass it into Nate's tag. The attributes on the tag allow you to simply chose which type of select you need as well as any other details you need to set for the selects.
If you want to write this yourself, use the CFWDDX tag to get from query from CF into an array in JS.
This JS function should help you populate any given select.
<script language='JavaScript' type="text/javascript">
function fillnextdropdown(default_v
// with == in the form
with (eval("document."+formname
if (selected_value != 0) {
// If a real selection has been made
// Set up the defaults and clear the Activity Year Options
NewOpt = new Option;
var OptionCount = 0;
thisField = eval(fieldname);
thisQuery = eval(queryname);
thisParentIDCol = eval("thisQuery."+ParentID
thisChildIDCol = eval("thisQuery."+ChildID)
thisdspColumn = eval("thisQuery."+dspColum
RowCount = thisParentIDCol.length;
thisField.options.length = 0;
// Add in a new top option
NewOpt.value = 0;
NewOpt.text = default_text;
thisField.options[OptionCo
// Now loop through the query we converted to a couple of arrays and output the appropriate options
for (var i = 0; i < RowCount; i++){
if (thisParentIDCol[i] == selected_value){
OptionCount++;
NewOpt = new Option;
NewOpt.value = thisChildIDCol[i];
NewOpt.text = thisdspColumn[i];
thisField.options[OptionCo
if (NewOpt.value == default_value)
thisField.selectedIndex = OptionCount;
}
}
}
}
}
</script>
Here is an example of a call of this function.
<select name="SubGroupID" class="formstyleblue" onchange="fillnextdropdown
<option value="0" class="bodytext">Select a Template Subscription Group >></option>
<cfoutput query="SubGroupTemplates" group="SubGroupID">
<option value="#SubGroupTemplates.
</cfoutput>
</select>
<select name="TemplateID" class="formstyleblue">
<option value="0">Select a Subscription Group from the list above</option>
</select>
These lines need to be included in the page to allow CFWDDX to create the JS array from the query for this example:
<script language='JavaScript' src='/cfide/scripts/wddx.j
<script language="JavaScript" type="text/javascript">
<cfwddx action="cfml2js" input="#SubGroupTemplates#
</script>
And this is the query that is used to populate the first select and the JS array
<cfquery name="SubGroupTemplates" datasource="#request.dsn#"
SELECT E.SubGroupID, E.Title, ET.TemplateID, CONCAT(ET.TemplateTitle,' (',ET.TemplateType,')') AS TemplateTitle
FROM EmailSubGroup E
INNER JOIN EmailTemplate ET ON E.SubGroupID=ET.SubGroupID
ORDER BY E.Title, ET.TemplateTitle
</cfquery>
https://www.experts-exchange.com/questions/20996834/Dropdown-population.html
and
https://www.experts-exchange.com/questions/20731750/ASP-NET-Clientside-Linked-Dropdown-Listbox.html