Solved

Coldfusion Ajax CFC - returning data

Posted on 2013-01-14
17
1,018 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Forrester Webinar: xMatters Delivers 261% ROI

Guest speaker Dean Davison, Forrester Principal Consultant, explains how a Fortune 500 communication company using xMatters found these results: Achieved a 261% ROI, Experienced $753,280 in net present value benefits over 3 years and Reduced MTTR by 91% for tier 1 incidents.

 
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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

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

Question has a verified solution.

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

Hi, I will be creating today a basic tutorial on how we can create a Mail Custom Function and use it where ever we want. The main advantage about creating a custom function is that we can accommodate a range of arguments to pass to the Function and …
Hi. There are several upload tutorials using jquery and coldfusion. I found a very interesting one here Upload Your Files using Jquery & ColdFusion and Preview them (http://www.randhawaworld.com/) . I did keep the main js functions but made sever…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

749 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