Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Returning Array from CFC to JavaScript

Explorer ,
May 29, 2009 May 29, 2009

I am trying to write a javascript that talks to a CFC and I need the CFC to return an Array that I can read back into the javascript (as a js array) and then loop through that list.

So in the CFC I create an array something like:

<CFFUNCTION name="getCity" access="remote" returnType="array">

     <CFSET var result = ArrayNew(2)>

     <CFSET result[0][1] = 1>

     <CFSET result[0][2] = “Vancouver”>

     <CFSET result[0][1] = 2>

     <CFSET result[0][2] = “Detroit”>

     <CFSET result[0][1] = 3>

     <CFSET result[0][2] = “Miami”>

     <CFRETURN result>

</CFFUNCTION>

Then in the JS return function:

function returnCity(returnArray) {

                for (var i=0; i<returnArray.length; i++) {

                                document.formname.cityID.options.value = returnArray[0];

                                document.formname.cityID.options.text = returnArray[1];

                }

}

4.9K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 29, 2009 May 29, 2009

<cfwddx> and toScript() are two ways to get Cold Fusion Data into js.  I don't know if js can handle 2D arrays, so I always to this with 2 1D arrays.

Here is a bit of a sample that shows using toScript() for something similar to what you are attempting.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 29, 2009 May 29, 2009

Outside of Dan's option, you can check out an Ajax library or two (jQuery, MooTools, Prototype) for this type of functionality. These libraries greatly simplify the communication b/w JS and server-side scripts (i.e., CFML). You can use 'regular' JS to run your XMLHttpRequest (http://en.wikipedia.org/wiki/XMLHttpRequest) but it's a good bit more coding than using a JS-Ajax library. Regardless of your approach (Ajax library or standard JavaScript), the XMLHttpRequest object is the key to browser-server communication of this nature.

Also, your JavaScript won't understand a CF array with these tools/libraries but you can use CF's SerializeJSON function to return JSON (JavaScript Object Notation) rom your CF data or just return the data as XML, either of which your JS can parse, loop over, handle as an array (sort of), etc.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
May 29, 2009 May 29, 2009

The <cfwddx...> tag is built to translate complex variables back and forth particularly with javascript.

<cfwddx action="cfml2js" input="#cfVar#" output="JSString" toplevelvariable="JSVarName">

In your code example that might look something like this.

CFML

<CFFUNCTION name="getCity" access="remote" returnType="array">
     <CFSET var result = ArrayNew(2)>
     <CFSET result[0][1] = 1>
     <CFSET result[0][2] = “Vancouver”>
     <CFSET result[0][1] = 2>
     <CFSET result[0][2] = “Detroit”>
     <CFSET result[0][1] = 3>
     <CFSET result[0][2] = “Miami”>
    
     <cfwddx action="cfml2js" input="#result#" output="returnString" topLevelVariable="returnArray">

     <CFRETURN returnstring>
</CFFUNCTION>

JavaScript

function returnCity(returnArray) {
                for (var i=0; i<returnArray.length; i++) {
                                document.formname.cityID.options.value = returnArray[0];
                                document.formname.cityID.options.text = returnArray[1];
                }
}

But I have never used this in a AJAX envornment.  In this you may have to create the wddx package in the CFML and decode this package in the JavaScript. oYou would then use the "cfml2wddx" action.  And you would have to include the JS wddx package to decode it.  The documentation explains how to do all of that.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 29, 2009 May 29, 2009

Well, I've tried about a million things and it isn't working. Currently I've been trying to follow the example on Adobe's site here:

http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_a-b_3.html

Here is what I have (I am  in ColdFusion 8 Enterprise):

Here is my current CFC:

<CFCOMPONENT output="no">

<!--- Return a verified member list of states/provinces --->

<CFFUNCTION name="getStateVerMem" access="remote" returnFormat="json">

<CFQUERY datasource="dsnname" name="getSt">

                                                SELECT stateID, stateAB FROM States

                                </CFQUERY>

<CFRETURN getSt>

       

</CFFUNCTION>

</CFCOMPONENT>

Here is my JS code:

<!--- Set AJAX Proxy --->

<CFAJAXPROXY cfc="cfc.event" jsclassname="evtreg">

<!--- Begin JavaScript processing ---->

<script language="javascript">

<!--

function returnMembership() {

                var fieldInput = new evtreg();

                fieldInput.setCallbackHandler(returnMemVerState);

                fieldInput.setErrorHandler(myErrorHandler);

                fieldInput.validateMembership();

}

// Update the verified member state

function returnMemVerState(returnString) {

                for (var i=0; i<returnString.DATA.length; i++) {

                                document.formname.stateID.options.value = returnString.DATA[returnString.COLUMNS.findIdx(‘STATEID’)];

                                document.formename.stateID.options.text = returnString.DATA[returnString.COLUMNS.findIdx(‘STATEAB’)];

                }

}

// Error handler for the asynchronous functions.

function myErrorHandler(statusCode, statusMsg){

                alert('We are sorry, an error occured on this form.' + statusCode + ', ' + statusMsg);

}

-->

</script>

When the function returnMembership is called this should return data and populate the dropdown, but I keep getting an error: “DATA.length is null or not an object

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 29, 2009 May 29, 2009

If I run the CFC in a web browser I get the following output:

{"COLUMNS":["STATEID","STATEAB"],"DATA":[[2,"AK"],[1,"AL"],[4,"AR"],[3,"AZ"],[5,"CA"],[6,"CO"],[7,"CT"],[48,"DC"],[8,"DE"],[9,"FL"],[10,"GA"],[11,"HI"],[15,"IA"],[12,"ID"],[13,"IL"],[14,"IN"],[16,"KS"],[17,"KY"],[18,"LA"],[21,"MA"],[20,"MD"],[19,"ME"],[22,"MI"],[23,"MN"],[25,"MO"],[24,"MS"],[26,"MT"],[33,"NC"],[34,"ND"],[27,"NE"],[29,"NH"],[30,"NJ"],[31,"NM"],[28,"NV"],[32,"NY"],[35,"OH"],[36,"OK"],[37,"OR"],[38,"PA"],[39,"RI"],[40,"SC"],[41,"SD"],[42,"TN"],[43,"TX"],[44,"UT"],[46,"VA"],[45,"VT"],[47,"WA"],[50,"WI"],[49,"WV"],[51,"WY"]]}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 29, 2009 May 29, 2009

I don't use cfajaxproxy but with all Ajax calls I make, I retuned JSON. Your CFC method is returning a query. CF has a function called SerializeJSON (http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_s_03.html). You can pass it a query and have it convert that (or a struct, string, boolean, etc.) it to JSON.

Chang e in bold:

<CFCOMPONENT output="no">

<!--- Return a verified member list of states/provinces --->

<CFFUNCTION name="getStateVerMem" access="remote" returnFormat="json">

<CFQUERY datasource="dsnname" name="getSt">

                                                SELECT stateID, stateAB FROM States

                                </CFQUERY>

<CFRETURN SerializeJSON( getSt )>

       

</CFFUNCTION>

</CFCOMPONENT>

Perhaps this conversion is something cfajaxproxy does but whenever my function/method needs to return JSON (didn't see any indication of this while skimming the docs), I convert my CF data types to JSON before the return.

What happens if you add alert( returnString ); to the first line of the returnMemVerState() function? Dos it read [Object object], show a string, etc.?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 29, 2009 May 29, 2009

With CF8 you can just tell it returnFormat="json" which does the same as the SerializeJSON (see my output above from the CFC).

I did run the alert(returnString) and received [Object object] as my response.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 29, 2009 May 29, 2009

Cool. Didn't know if that was one of CF's auto-magic conversions (I use CF8 but not those tags/features).

You might want to try this JavaScriot function: dump()

Code here: http://www.openjs.com/scripts/others/dump_function_php_print_r.php

It'll basically dump a JS object and you should get a better view of what's coming bak to you.

Here's one inspired by cfdump:

http://www.netgrow.com.au/files/javascript_dump.cfm

Finally, do you have Firefox & Firebug? If so, Firebug shows you the raw data returned from your Ajax calls. It can be very, very helpful!

Also, keep in mind JS is case-sensitive, so returnString.data is different than returnString.DATA. I've burned myself on that one plenty of times!!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 29, 2009 May 29, 2009

Wierd, when I dump I get the following:

object
MYRETURNVAL [number]0


Shouldn't that be the same as the output I receive when I run the CFC manually?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 29, 2009 May 29, 2009

That's what I would expect, too. Or, at least an object-based representation of the CF-generated JSON. It would seem that CF isn't returning anything to the JS function but that it's creating the correct JSON.

It doesn't seem likely but do you need to add the onSuccess attribute to

<CFAJAXPROXY cfc="cfc.event" jsclassname="evtreg">

I know your setting stuff herer

function returnMembership() {

                var fieldInput = new evtreg();

                fieldInput.setCallbackHandler(returnMemVerState);

                fieldInput.setErrorHandler(myErrorHandler);

                fieldInput.validateMembership();

}

But I wonder if it would make a difference if you went the route of

<CFAJAXPROXY cfc="cfc.event" onSucces="returnMemVerState" onError="myErrorHandler">

You shouldn't have to change your JS at all for that test.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 29, 2009 May 29, 2009

Well, the issue is that I am running other function calls with the code that are returning correct results. Just this one is being screwy for some reason.

Maybe I'll try isolating this call onto it's own CFAJAXPROXY. I haven't tried that before.

Thanks for your great help so far.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 29, 2009 May 29, 2009

Well, you can't add those props into the cfajaxproxy this way as it causes this error:

Error in custom script module
(/customcf/event_registration.cfm)
Invalid attribute. The attributes onsuccess or onerror cannot be used with the CFC attribute.

I am just stumped as to why the output works manually, but it won't return it to my script. I'll have to try and remove everything else and isolate just this piece.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 29, 2009 May 29, 2009
LATEST

I wanted to make sure the dump functions were working, so I just ran this code (first dump function) and it dumped he data correctly

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

     <head>

     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

          <title>Untitled Document</title>

         <script type="text/javascript" src="lib/dump/dump.js"></script>

          <!-- <script type="text/javascript" src="lib/dump/cf_dump.js"></script> -->

          <script type="text/javascript">

               function init() {

                    var assoc = {"COLUMNS":["STATEID","STATEAB"],"DATA":[[2,"AK"],[1,"AL"],[4,"AR"],[3,"AZ"],[5, "CA"],[6,"CO"],[7,"CT"],[48,"DC"],[8,"DE"],[9,"FL"],[10,"GA"],[11,"HI"],[15,"IA" ],[12,"ID"],[13,"IL"],[14,"IN"],[16,"KS"],[17,"KY"],[18,"LA"],[21,"MA"],[20,"MD" ],[19,"ME"],[22,"MI"],[23,"MN"],[25,"MO"],[24,"MS"],[26,"MT"],[33,"NC"],[34,"ND" ],[27,"NE"],[29,"NH"],[30,"NJ"],[31,"NM"],[28,"NV"],[32,"NY"],[35,"OH"],[36,"OK" ],[37,"OR"],[38,"PA"],[39,"RI"],[40,"SC"],[41,"SD"],[42,"TN"],[43,"TX"],[44,"UT" ],[46,"VA"],[45,"VT"],[47,"WA"],[50,"WI"],[49,"WV"],[51,"WY"]]};

                    alert(dump(assoc));

               }

               window.onload=init;

          </script>

     </head>

     <body>

     </body>

</html>

I then ran this code (cfdump-inspired) function:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

    <head>

          <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

          <title>Untitled Document</title>

          <!-- <script type="text/javascript" src="lib/dump/dump.js"></script> -->

          <script type="text/javascript" src="lib/dump/cf_dump.js"></script>

          <script type="text/javascript">

               function init() {

                    var assoc = {"COLUMNS":["STATEID","STATEAB"],"DATA":[[2,"AK"],[1,"AL"],[4,"AR"],[3,"AZ"],[5, "CA"],[6,"CO"],[7,"CT"],[48,"DC"],[8,"DE"],[9,"FL"],[10,"GA"],[11,"HI"],[15,"IA" ],[12,"ID"],[13,"IL"],[14,"IN"],[16,"KS"],[17,"KY"],[18,"LA"],[21,"MA"],[20,"MD" ],[19,"ME"],[22,"MI"],[23,"MN"],[25,"MO"],[24,"MS"],[26,"MT"],[33,"NC"],[34,"ND" ],[27,"NE"],[29,"NH"],[30,"NJ"],[31,"NM"],[28,"NV"],[32,"NY"],[35,"OH"],[36,"OK" ],[37,"OR"],[38,"PA"],[39,"RI"],[40,"SC"],[41,"SD"],[42,"TN"],[43,"TX"],[44,"UT" ],[46,"VA"],[45,"VT"],[47,"WA"],[50,"WI"],[49,"WV"],[51,"WY"]]};

                    //alert(dump(assoc));

                    dump( assoc, true );

               }

               //window.onload=init;

          </script>

     </head>

     <body>

          <a href="#" onclick="init()">dump</a>

     </body>

</html>

This also showed me the JSON data in the CFDUMP way I expected.

In both cases, the included JS files only contain the previously linked-to dump functions. It seems rather odd that CF isn't returning the correct data. Sorry I don't know more about cfajaxproxy!

Message was edited by: craigkaminsky -- took out single quotes surrounded assoc var to get correct dump output

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources