views:

64

answers:

3

I have a ColdFusion CFC function like this:

<cffunction access="remote" name="getResults"
    returntype="struct"
    returnformat="JSON"
    output="no">

    <cfargument name="q" required="true" type="array" />

...
</cffunction>

How do I call this function from jQuery? Neither form of array encoding by jQuery will get ColdFusion to see the value as array.

If you pass "q=a&q=b" (like with jQuery.ajaxSettings.traditional = true), the function will get the string "a,b", not an array. While splitting on comma may seem like a possibility, it will not work if one of the "q" values contains a comma. Also, ideally, the function on the server-side should not have to be aware of the problems of how to serialize the data over the wire, and should continue to take in an array.

If you pass "q[]=a&q[]=b" (the jQuery default), it will not map over to the "q" parameter. If you try to change the name of the "q" parameter to "q[]", the CFC will error out due to an invalid parameter name.

A: 

How about checking your values for commas and escaping them before passing to Coldfusion, then use ListToArray to convert and (if necessary) re-encode the commas?

Daniel Mendel
Ideally the CFC function shouldn't have to change, so that it can be called on the server-side in a normal fashion. I've updated the question to clarify that.
jrduncans
Understood, it looks like you found a good solution.
Daniel Mendel
+2  A: 

Investigating this problem, I found the following blog post: http://www.coldfusionjedi.com/index.cfm/2010/3/23/Using-jQuery-to-post-an-array-to-a-ColdFusion-Component - This suggested encoding the array as a JSON string, and then deserializing it inside the CFC method, with the unfortunate impact of requiring the CFC function to have to change to deal with JSON.

So I investigated further, and here's the best solution I have found so far.

By looking at the HTTP calls made when using cfajaxproxy, I discovered that you can send a single argumentCollection parameter as a JSON string to call the remote CFC method.

So the client side call looks something like this (using jquery-json plugin to do the serialization):

var params = {q: ['a', '1,2,3']};

$.getJSON('My.cfc?method=getResults', {argumentCollection: $.toJSON(params)}, function(data) {
// handle data
});
jrduncans
psst... I think you dropped a `]` somewhere.
Daniel Mendel
+1  A: 

First thing to know is jQuery Ajax requests do not encode arrays so have you to use something else to encode the data (this is where jquery.JSON.js comes from referenced below). So with a the JSON encoded found there, I then figured out the correct syntax by working with cfajaxproxy and studying the URL it generates in Firebug:

http://localhost/remote.cfc?method=getResults&amp;argumentCollection=%7B%22q%22%3A%5B1%2C2%5D%7D

Yes the "argumentcollection" approach is correct, and the variable "q" with a reference to an array is in there.

I used the following code as a test bed:

remote.cfc

<cfcomponent output="false">
    <cffunction access="remote" name="getResults"
        returntype="struct"
        returnformat="JSON"
        output="no">

        <cfargument name="q" required="true" type="array" />

        <cfreturn {a=1,b=2}>
    </cffunction>
</cfcomponent>

remote.cfm to see how cfajaxproxy generates its url

<cfajaxproxy cfc="Remote" jsclassname="Remote">
<cfoutput>
<script language="javascript" type="text/javascript">
var oRemote = new Remote();
alert(oRemote.getResults([1,2]));
</script>
</cfoutput>

remote.html doing it with jQuery

<script language="javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"&gt;&lt;/script&gt;
<script language="javascript" src="jquery.JSON.js"></script>
<script language="javascript" type="text/javascript">
var argumentCollection = { q: [1,2] };
$.ajax({
    url:        'remote.cfc',
    data:       {
        method: 'getResults',
        argumentCollection: $.JSON.encode(argumentCollection)
    },
    success:    function(response) {
        alert(response);
    },
    dataType:   'json'
});

</script>
orangepips
Well, I'd say that jQuery does encode arrays, just not in a way that ColdFusion can accept. By default in jQuery 1.4.3, arrays are encoded in a fashion compatible with PHP and Ruby on Rails, by providing multiple parameters, with a parameter name that adds "[]" to the variable name. Using the "traditional" setting, it encodes them the same way an HTML form does for multiple checkboxes, just sending multiple of the parameter. Your approach for figuring this out matched mine. Thanks for the detailed sample code!
jrduncans