ColdFusion and Ajax Dropdown

Trying to get drop downs to populate based on selection. Have this component.

<cfcomponent output="false">

<!--- Get array of media types --->
<cffunction name="getMake" access="remote" returnType="array">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>

<!--- Get data --->
<cfquery name="data" datasource="#APPLICATION.VCDBDSN#">
select * from make where Active = '1'
</cfquery>

<!--- Convert results to array --->
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.MakeID[i]>
<cfset result[i][2]=data.MakeName[i]>
</cfloop>

 <!--- And return it --->
<cfreturn result>
</cffunction>

<!--- Get art by media type --->
<cffunction name="GetYear" access="remote" returnType="array">
<cfargument name="MakeID" type="numeric" required="true">

<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>

<!--- Get data --->
<cfquery name="data" datasource="#APPLICATION.VCDBDSN#">
select distinct YearID
From BaseVehicle  
INNER JOIN Make (nolock) on Make.MakeID=BaseVehicle.MakeID
INNER JOIN Model (nolock) on Model.ModelID=BaseVehicle.ModelID
where Make.MakeID='2'
Order by BaseVehicle.YearID DESC
</cfquery>
   
<!--- Convert results to array --->
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.YearID[i]>
</cfloop>

<!--- And return it --->
<cfreturn result>
</cffunction>
</cfcomponent>




And this file


<cfobject component = "test" name = "test">






<cfform>
<table>
<tr>
<td><cfselect name="MakeID"
bind="cfc:test.getMake()" bindonload="true" /></td>
</tr>
<tr>
<td>Select Art:</td>
<td><cfselect name="YearID" bind="cfc:test.GetYear({MakeID})" /></td>
</tr>
</table>
</cfform>


its now working.  Never did this kind of thing before. What's wrong?
Kamilek0617Asked:
Who is Participating?
 
_agx_Commented:
These three things should fix the error

Change the form so that both lists are bindOnLoad="true":
    <cfselect name="YearID" bind="cfc:test.GetYear({MakeID})"  bindOnLoad="true"/>

In the GetYear() function, use argument type to "string". Otherwise, an error may occur if nothing is selected in the MakeID list.  Obviously validate the value inside your function ...

          <cfargument name="MakeID" type="string" required="true">
          ...

In the GetYear() function, you forgot to populate the second element of the array

<!--- Convert results to array --->
<cfloop index="i" from="1" to="#data.RecordCount#">
<cfset result[i][1]=data.YearID[i]>
<cfset result[i][2]=data.YearID[2]>   <!---- THIS LINE IS MISSING --->
</cfloop>
0
 
erikTsomikSystem Architect, CF programmer Commented:
you need to use <cfajaxproxy before you invoke the cfc
0
 
Kamilek0617Author Commented:
How?
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
erikTsomikSystem Architect, CF programmer Commented:
do you get any errors
0
 
_agx_Commented:
Erik - why do you keep saying cfajaxproxy is needed?! ;-) It's not. That's not what cfajaxproxy is used for.

> its now working.  

Did you test the CFC first to make sure it works? Also, enable the ajax debugging logger in the CF Admin. So you can see any ajax errors occurring.  Make sure to add ?cfdebug onto the URL of the form page:

http://yourservername/yourFormPage.cfm?cfdebug
0
 
erikTsomikSystem Architect, CF programmer Commented:
first dump the cfc data to insure that data is actually being return for the first drop down
0
 
Kamilek0617Author Commented:
No errors, nothing.  Just to empty boxes.  I put both queries into a .cfm file and run the file, but queries dumped out the results.  
0
 
_agx_Commented:
> Enable the ajax debugging logger in the CF Admin. So you can see any ajax errors occurring.  
> Make sure to add ?cfdebug onto the URL of the form page:

Did you see my comment?

0
 
Kamilek0617Author Commented:
_agx_:  Nope. did all 3 and nothing.  
0
 
Kamilek0617Author Commented:
Debugging shows me this:

info:http: CFC invocation response:   [[1,"Suzuki "],[2,"Porsche "],[3,"Hyundai "],[7,"Fiat "],[11,"Land Rover "],[13,"Subaru "],[14,"Triumph "],[16,"Alfa Romeo "],[18,"Daewoo "],[19,"Daihatsu "],[20,"Jaguar "],[21,"Kia "],[22,"Opel "],[27,"Volvo "],[28,"Peugeot "],[31,"BMW "],[32,"Mini "],[37,"Isuzu "],[38,"Lamborghini "],[39,"Chrysler "],[40,"Dodge "],[41,"Eagle "],[42,"Jeep "],[43,"Plymouth "],[44,"AM General "],[45,"Buick "],[46,"Cadillac "],[47,"Chevrolet "],[48,"GMC "],[50,"Geo "],[51,"Oldsmobile "],[52,"Pontiac "],[54,"Ford "],[55,"Lincoln "],[56,"Mercury "],[57,"Merkur "],[58,"Acura "],[59,"Honda "],[62,"Maybach "],[63,"Mercedes-Benz "],[64,"MG "],[65,"Saab "],[67,"Nissan "],[68,"Infiniti "],[69,"Bentley "],[70,"Rolls Royce "],[72,"Mitsubishi "],[73,"Audi "],[74,"Volkswagen "],[75,"Lexus "],[76,"Toyota "],[77,"Aston Martin "],[78,"Ferrari "],[79,"Maserati "],[80,"Mazda "],[95,"Bugatti "],[484,"Smart "],[679,"Dove "],[701,"Goldoni "]]
info:http: HTTP GET /Test/test.cfc?method=getMake&returnFormat=json&argumentCollection=%7B%7D&_cf_nodebug=true&_cf_nocache=true&_cf_clientid=114B8433B8288AC82151CD06F0A20475&_cf_rc=0
info:http: Invoking CFC: /Test/test.cfc , function: getMake , arguments: {}
info:LogReader: LogReader initialized
info:global: Logger initialized
0
 
_agx_Commented:
Is that the whole log? Because your code works perfectly for me.

> info:http: CFC invocation response: Â  [[1,"Suzuki "],[2,"Porsche "],[3,"Hyundai "],[7, .....]
You can see it's returning data. But you're saying the lists don't contain any items?

0
 
azadisaryevCommented:
>> Â  [[1,"Suzuki "]

it looks like your Application.cfm/cfc is outputting something that gets prepended to the cfc responce, thus breaking JSON data format...

Azadi
0
 
Kamilek0617Author Commented:
Removed everything from application.cfc except

<cfcomponent output="no">
      <cfscript>
            this.name = "Mytestsite";
            this.applicationTimeout = createTimeSpan(0,1,0,0);
            this.sessionmanagement = "yes";
            this.sessiontimeout = createTimeSpan(0,0,30,0);
            this.scriptProtect = "all";  
      </cfscript>
      
      <cffunction name="onApplicationStart" output="false">
            <cfscript>
                  APPLICATION.title = "Test";
                  APPLICATION.DSN = "TestData";
                  APPLICATION.VCDBDSN="Vdb";
            </cfscript>
            
            <cfreturn true>
      </cffunction>

</cfcomponent>


Still doesn't work.  Just see 2 blank, non populated drop downs.  Using CF 9
0
 
azadisaryevCommented:
still that  prepended to returned json worries me...

do you have 'secure JSON' enabled in cf admin?
what is 'secure JSON prefix' set to?

if you have secure jhson DISabled, then something somewhere along the way is adding that  ...
i thought it may be a unicode BOM signature, but just tested it and cfc binding works just fine even if a file is saved as utf-8 with BOM...

on a whim:
try changing your <cfselect ... /> to full closing tag: <cfselect ...></cfselect>

Azadi
0
 
_agx_Commented:
> still that  prepended to returned json worries me...

  Good catch.
0
 
Kamilek0617Author Commented:
Got rid of the Â.

Now the makes get populated correctly.  But the year, is always as 2009, but about 50 times.  No matter if anything is selected or not selected in the make.
0
 
azadisaryevCommented:
>> But the year, is always as 2009, but about 50 times

i guess that's what the query in your getYear cfc function returns. you seem to have hard-coded the MakeID value there (at least in your original post). i also think you do not need the second inner join in that query - there does not seem top be anything in Model table you need for this query...

>> No matter if anything is selected or not selected in the make

remove bindonload="true" from your YearID cfselect if you have added it there.

>> Got rid of the Â.

may i ask where was it coming from? just curious...

Azadi
0
 
Kamilek0617Author Commented:
The  sometimes happens when I copy code with Google Chrome form a webpage and paste it into dreamweaver.  It just shows up as blank space in dreamweaver so I have to guess where it could be and remove all blank spaces.  Pain in the ass.

My form code looks like this so there is no bind.

<cfform>
<table>
<tr>
<td><cfselect name="MakeID"
bind="cfc:test.getMake()" bindonload="true" /></td>
</tr>
<tr>
<td>Select Art:</td>
<td><cfselect name="YearID" bind="cfc:test.GetYear({MakeID})" /></td>
</tr>
</table>
</cfform>

I changed my cfc code to

<cfquery name="data" datasource="#APPLICATION.VCDBDSN#">
select distinct YearID
From BaseVehicle
INNER JOIN Make (nolock) on Make.MakeID=BaseVehicle.MakeID
INNER JOIN Model (nolock) on Model.ModelID=BaseVehicle.ModelID
where Make.MakeID='#Arguments.MakeID#'
Order by BaseVehicle.YearID DESC
</cfquery>

Still just 2009 shows up right away and never changes.  
0
 
azadisaryevCommented:
try changing your query to this:

<cfquery name="data" datasource="#APPLICATION.VCDBDSN#">
SELECT DISTINCT bv.YearID
FROM BaseVehicle bv
INNER JOIN Make (nolock) ON Make.MakeID = bv.MakeID
WHERE Make.MakeID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.MakeID#">
ORDER BY YearID DESC
</cfquery>

change cfsqltype if necessary.

btw, are you sure your query should return any other year apart from 2009?

Azadi
0
 
Kamilek0617Author Commented:
No difference.  

0
 
azadisaryevCommented:
ok, let simplify it even more:

<cfquery name="data" datasource="#APPLICATION.VCDBDSN#">
SELECT DISTINCT YearID
FROM BaseVehicle
WHERE MakeID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.MakeID#">
ORDER BY YearID DESC
</cfquery>

again, are you certain that you have any years in your BaseVehicle table other than 2009?

Azadi
0
 
Kamilek0617Author Commented:
No change.  Yes, positive that I have lots of years in there, many years for every vehicle.

The problem here is that I don't even have to select a make.  As soon as I load the page, with nothing selected, it still loads about 50 items in the year drop down all of them being 2009 year.
0
 
Kamilek0617Author Commented:
I don't think the year field should load anything until I select a make to begin with.
0
 
Kamilek0617Author Commented:
Ah, got it.  <cfset result[i][2]=data.YearID[i]> was wrong.

Now, how do I make the year disabled and how do I only enable it when a make is selected?
0
 
azadisaryevCommented:
>> how do I make the year disabled and how do I only enable it when a make is selected?

try adding bindonload="false" to your <cfselect>

Azadi
0
 
Kamilek0617Author Commented:
No, still just loads.  Maybe because Acura is pre-selected in the make drop down.  How can I add a "select Make" to the make drop down and not have the year load until the make is selected?
0
 
azadisaryevCommented:
yes, by default the first option in <select> element is pre-selected.

you can use a UNION query to add a 'Select Make...' value:

<cfquery name="data" datasource="#APPLICATION.VCDBDSN#">
SELECT 0 AS MakeID, 'Select Make...' AS MakeName, 0 AS sortcol
FROM Make
UNION
SELECT MakeID, MakeName, 1 AS sortcol
FROM Make
WHERE Active = 1
ORDER BY sortcol, MakeName
</cfquery>

[some dbs may require each SELECT staement to be enclosed in ( ) ]

Azadi
0
 
_agx_Commented:
I object. The original question was how to fix two non-working bound select lists.  This question was answered (In part Azadi and in part by myself)  Now a new question was added to this thread:

    Now, how do I make the year disabled and how do I only enable it when a make is selected?

I think the previous answers should be accepted and a new thread opened for the new question.
0
 
Kamilek0617Author Commented:
You are right.  Sorry.
0
 
azadisaryevCommented:
[rant]

now that is a strange solution to accept...

if you can't spare a moment to properly close a question, i am not sure i want to waste my time trying to help you...

Azadi
0
 
_agx_Commented:
I think maybe they were just rushing.  But, I would have to agree.  As I suggested earlier, I think it should have been some sort of split between Azadi and myself.  IMO the two suggestions that solved the bind issue are:

ID: 31326615  _azadisaryev_    (JSON issue)
ID: 31310022  _agx_   (argument type / missing array element)
0
 
_agx_Commented:
I don't see how this was an improvement ... ;-) Not to mention the solution involved 2 parts, provided by 2 experts.
0
 
_agx_Commented:
My recommendation is #3 - Accept the comments below as the solution. Having tested the original code, there were 3 issues preventing it from working as expected:

http:#31326615  _azadisaryev_    
An invalid character in data caused an error when parsing the JSON result.

http:#31310022  _agx_  
An incorrect argument type _and_ missing array dimension caused an error when the CFC function was called.

Once these 3 issues were corrected, the code works just fine - as the asker originally agreed in response http:#32657037.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.