Solved

Coldfusion Ajax CFC - returning data

Posted on 2013-01-14
17
991 Views
Last Modified: 2013-01-15
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
0
Comment
Question by:hefterr
  • 6
  • 6
  • 5
17 Comments
 
LVL 10

Assisted Solution

by:stu215
stu215 earned 200 total points
ID: 38774914
<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
 
LVL 52

Accepted Solution

by:
_agx_ earned 300 total points
ID: 38775002
(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
 
LVL 1

Author Comment

by:hefterr
ID: 38776474
@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
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 52

Expert Comment

by:_agx_
ID: 38776908
(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
 
LVL 1

Author Comment

by:hefterr
ID: 38778329
@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
 
LVL 10

Expert Comment

by:stu215
ID: 38778923
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
 
LVL 1

Author Comment

by:hefterr
ID: 38778965
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
 
LVL 10

Expert Comment

by:stu215
ID: 38779007
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
 
LVL 52

Expert Comment

by:_agx_
ID: 38779379
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
 
LVL 1

Author Closing Comment

by:hefterr
ID: 38779407
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
 
LVL 52

Expert Comment

by:_agx_
ID: 38779521
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
 
LVL 1

Author Comment

by:hefterr
ID: 38780038
@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
 
LVL 10

Expert Comment

by:stu215
ID: 38780062
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
 
LVL 52

Expert Comment

by:_agx_
ID: 38780067
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
 
LVL 52

Expert Comment

by:_agx_
ID: 38780070
Oops, sorry guys.  Took too long typing and our responses overlapped,
0
 
LVL 10

Expert Comment

by:stu215
ID: 38780081
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
 
LVL 1

Author Comment

by:hefterr
ID: 38780321
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

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

PROBLEM:  How to open a cfwindow or run a function on double click of a cfgrid row. One of my clients wanted to be able to double click on a row item to get more detailed information about a transaction and to be able to modify the line items i…
PROBLEM: How to add your own buttons to the bottom toolbar with paging info ( result count ). While creating a cfgrid, I ran into an issue where I wanted to embed my own custom buttons where the default ones ( insert / delete / etc… ) are for aes…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question