Coldfusion Ajax CFC - returning data

Hi,
I need to write a quick remote cfc for a client side JQuery request for 4 fields on a table.

I will get 1 parameter sent to me "image file name" and I will return 4 columns from a table to be moved by the Jquery to 4 text fields.

<cffunction name="imageData"  access="remote" returnType="any" output="no">
      <cfargument name="imageKey" type="any" default="">

<cfquery name="getImage" datasource="myappdsn">
  Select column1, column2, column3, column4
   from Slide  where imageFile = #arguments.imageKey#

<CFreturn ??????>

</cffunction>

Open in new window


Q:   How do I return the data to the Jquery call?  Do I create a JSON string?  How do I do that?

For extra credit, how does the JQuery code parse this data to populate 4 text fields on the page?

Thanks in advance,
hefterr
LVL 1
hefterrAsked:
Who is Participating?
 
_agx_Commented:
(I'm not a jquery guru, but since I had already written this starter example before seeing stu's response, may as well post it ;-)

Test

/test/MyComponent.cfc
<cfcomponent>

	<cffunction name="imageData"  access="remote" returnType="any" output="no">
     	<cfargument name="imageKey" type="any" default="">

		<cfset var result = {} />
		<cfset var row = "" />
		
		<!--- (testing only) simulate your db query --->
		<cfset var getImage = queryNew("")>
		<cfset queryAddColumn(getImage, "column1", listToArray("Value 1"))>
		<cfset queryAddColumn(getImage, "column2", listToArray("Value 2"))>
		<cfset queryAddColumn(getImage, "column3", listToArray("Value 3"))>
		<cfset queryAddColumn(getImage, "column4", listToArray("Value 4"))>
		
		<cfloop query="getImage">
			<!--- MUST use struct["keyName"] syntax to preserve case ---> 
			<cfset row = {}>
			<cfset row["column1"] = column1 >
			<cfset row["column2"] = column2 >
			<cfset row["column3"] = column3 >
			<cfset row["column4"] = column4 >
			<cfset result["data"] = row>
		</cfloop>
		
		<cfreturn result>
	</cffunction>
</cfcomponent>

Open in new window


<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>	
<script type="text/javascript">
$(document).ready(function() {
		$("#testButton").bind("click",function() {
			var key = document.getElementById('imageKey').value;
			var request = $.ajax({url: "/test/MyComponent.cfc?method=imageData&returnFormat=json"
								, type: "get"
								, dataType: "json"
								, data: {imageKey : key}
					});
			request.done( function(data) {
				populateFields(data);
			});
			request.fail( function(jqXHR, status) {
				alert("Failed: "+ status);
			});
		});
	});

function populateFields(response) {
	alert(response.data);
	if (response.data) {
		$("#field1").val(response.data.column1);
		$("#field2").val(response.data.column2);
		$("#field3").val(response.data.column3);
		$("#field4").val(response.data.column4);
	}
}	
</script>

</head>
<body>
	imageKey <input id="imageKey" type="text">
	<input id="testButton" type="button" value="Test" ><hr>
	
	<input id="field1" type="text"><br>
	<input id="field2" type="text"><br>
	<input id="field3" type="text"><br>
	<input id="field4" type="text"><br>
</body>
</html>

Open in new window

0
 
stu215Systems AnalystCommented:
<cffunction name="imageData"  access="remote" returnType="any" output="false" returnformat="JSON">


<!--- convert to json --->
 <cfreturn serializeJSON(yourResult)>

You can return data in a variety of ways it just depends on how you read it in when it gets back.
( Firefox with Firebug installed helps a lot for debugging and seeing return results. )

You could also do:
<cffunction name="imageData"  access="remote" returnType="query" output="false" returnformat="JSON">

<cfreturn yourQueryName>

The jQuery.get function should handle your restults:
http://api.jquery.com/jQuery.get/

 url - the cfc you are submitting to
data - being sent to cfc
callback - what function to run or to do when the data comes back
"Json" - the data type being transmitted

jQuery.get(url, data, callback, "json");
0
 
hefterrAuthor Commented:
@agx,
1)  Could you give me an overview of what you are building.  It looks like a CF structure "result" that has one key item (result.data)?  This contains another structure called "row" which contains row.column1, row.column2,row.column3 and row.column4?

Q:  Why does this ned to be built this way?

Q:  How can I see the result.  Can I use CFHTTP in a test program?

Q:  Do I need to indicate JSON in my CFC anywhere?

2)  Is the reference to :
                  request.done( function(data) {
                        populateFields(data);
                  });

tie back to the structure "data" or is that a JQuery special reference?

Thanks!
hefterr
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
_agx_Commented:
(Sorry I got caught up in other stuff...)

an overview of what you are building

"row" is just a temporary value used in construction. The actual result returned is a structure that contains a key named "data". "data" is itself a structure which contains 4 keys - one for each of the columns in your query.   ie  result.data.column1, result.data.column2, etc...  Here's what the json looks like

{"data":{"column4":"Value 4","column2":"Value 2","column3":"Value 3","column1":"Value 1"}}

Open in new window



Q:  How can I see the result.  Can I use CFHTTP in a test program?

You can view the results in your browser. Just adjust the url to match the path of your cfc:

   http://localhost/test/MyComponent.cfc?method=imageData&returnFormat=json&imageKey=someValueHere

Q:  Do I need to indicate JSON in my CFC anywhere?

You can, but don't *need* to. It's already done in the jquery url by adding the param:

           &returnFormat=json

(Doing it via url makes the function more flexible)

Q:  Why does this ned to be built this way?

Again, you don't *have* to build it that way. I chose that structure based on some assumptions about your process, like query returns 1 row of data, etc.. But you could easily structure it differently.  

tie back to the structure "data" or is that a JQuery special reference?

Neither. The name "data" is just a coincidence. You can assign any variable name, for example, I could have used "foo":

                  request.done( function(foo) {
                        populateFields(foo);
                  });

> alert(response.data);

BTW, you can remove that line. It was just for testing.
0
 
hefterrAuthor Commented:
@both

Stu simply returned the query itself.  Does this change the JQuery fielding the results?  What type of JSON does this produce?

agx packaged a structure.

Is there a good reason for one versus theother.

I really learned a lot from this post.  This is my first time using our own JQuery/AJAX.

hefterr
0
 
stu215Systems AnalystCommented:
Check out this link which explains the "serializeJSON" function and shows what the query return would look like: ( has an example + the output )

http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_s_03.html
0
 
hefterrAuthor Commented:
Hi stu215.
I was under the impression that the returned data would automatically undergo a conversion to JSON if the calling JQuery script indicated as such.

But the link was helpful to how the conversion is done for different data structures in CF.

hefterr
0
 
stu215Systems AnalystCommented:
I didnt have an example at the time but this is what a straight query return would look like:

<cffunction name="getEmps" output="false" access="remote" returntype="any" returnformat="JSON">
        <cfargument name="myDeptID" type="string" required="yes" default="">

        <cfquery name="getPeeps" datasource="general" maxrows="4">
           ... my Query ...
          </cfquery>

        <cfreturn getPeeps>
 </cffunction>  

The Results:

{"COLUMNS":["MYNAME","USERNAME","CUST_ID","FLAG"],"DATA":[["Abd, sha","abdsha444",null,"Y"],["Abc, Mike","Abc666 ",null,"Y"],["Ada, Jay","Ada555 ",null,"Y"],["Air, Kat","AirK222 ",null,"Y"]]}
0
 
_agx_Commented:
Does this change the JQuery fielding the results?  What type of JSON does this produce?

The JSON is the same, only the structure of the result ie keys are different.

agx packaged a structure...
Is there a good reason for one versus the other.


You can do either. The advantage of just returning a query is it's simpler to code on the CF side. But the disadvantage is CF automatically converts all the keys to upper case, which is non-standard. (By that I just mean different than most of your typical API's, but the json is still perfectly valid). Because javascript is case sensitive, the consuming code must also use all upper case. Both work, its just a matter of what result you want.

I was under the impression that the returned data would automatically undergo a conversion to JSON if the calling JQuery script indicated as such.

It does. Adding   &returnFormat=json to the URL automatically converts the result to JSON.  So you can use the function multiple ways. Just add the url param when you want JSON. You could also use serializeJSON inside the function, but then it will always return JSON, making it a little less flexible.
0
 
hefterrAuthor Commented:
Thanks for your help on this.  I may have other questions - but I'll open them up in another question or to the JQuery forum if needed.
0
 
_agx_Commented:
Welcome.

     > CF automatically converts all the keys to upper case

(Edit) Two things I forgot to stress.  That applies to any structure. The only way to force CF to preserve the case of structure keys is to use this syntax (Dot notation *won't* work)

               <cfset yourStruct["keyName"] = "something">

Second,  the "&returnFormat=json" param has nothing to do with jquery. It's pure CF. CF sees that parameter in the URL and automatically converts the response to json format.
0
 
hefterrAuthor Commented:
@agx,
The only way to force CF to preserve the case of structure keys
This is a very lame question, but do you mean the "case" of the key name or the "case" of the key value.  I assume you are referring to the case of the value.
0
 
stu215Systems AnalystCommented:
Agx is referring to how the data is returned from the CFC:

This is how it should look:
{"data":{"column4":"Value 4","column2":"Value 2","column3":"Value 3","column1":"Value 1"}}

Coldfusion would make it all caps ( Caps are not standard ) and programs will have issues.

You can kinda see this from my data return using CF:
{"COLUMNS":["MYNAME","USERNAME","CUST_ID","FLAG"],"DATA":[["Abd, sha","abdsha444",null,"Y"],["Abc, Mike","Abc666 ",null,"Y"],["Ada, Jay","Ada555 ",null,"Y"],["Air, Kat","AirK222 ",null,"Y"]]}
0
 
_agx_Commented:
The key name. If you create a structure with dot notation:
              <cfset myStruct.someKeyName = "foo">

When CF converts it to json, it will look like something like this:
             { SOMEKEYNAME: "foo" }

But if you used this syntax:

              <cfset myStruct["someKeyName"] = "foo">

CF will preserve the exact case of the key name and the json result will be:

             { someKeyName: "foo" }
0
 
_agx_Commented:
Oops, sorry guys.  Took too long typing and our responses overlapped,
0
 
stu215Systems AnalystCommented:
Sall good :-P

-- You can handle it on the return side if you want but generally its easier to return standard data & to do any processing to your data before returning it.
0
 
hefterrAuthor Commented:
You guys re GREAT!  Big help getting into CF/JQuery/AJAX.  I am working with a front end colleague doing the JQuery - but she is a bit new to this also.  So thanks again,

hefterr
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.