Wow, this is a cool tip. I've had this in my queue to write about for a few weeks now but I was delayed due to MAX. Credit for this goes to Stephen Duncan Jr - I'm just passing it along - and to be honest - it kinda seems obvious now - but it's certainly not something I've thought of before. I've said it before - but I'll say it again. I love my readers.
Back in March I blogged about an interesting problem I ran into with jQuery and CFCs. This wasn't a jQuery specific issue, but as I use jQuery most of the time I ran into it there. I won't repeat the entire previous blog entry, but the basic problem was that there didn't seem to be a good way to post arrays of data to a back end CFC. jQuery does serialize the array, but it does it in a way that makes CFCs sad. My solution was to encode the array into JSON and update my CFC to accept either "real" arrays or JSON-encoded arrays. It worked... but I hated modifying my CFC.Fast forward a few months and a reader, Stephen Duncan JR, pointed out something interesting. If you read his comment, you will see he did something a bit different. Instead of simply passing data=json version of array, he passed a JSON-encoded version of a structure containing name-value pairs. He used the argumentCollection feature of CFCs.
If this is the first time you've heard of argumentCollection, don't be surprised. It is documented but not used very often. It's based on an even older feature, attributeCollection, that is used in custom tags. argumentCollection allows you to pass a structure of names and values. ColdFusion will treat this as if they were real arguments and values. So consider a structure data that contains:
name=ray
age=37
coolness=epic
If you pass argumentCollection=data to a CFC method (or any UDF), then ColdFusion acts as if you had passed arguments name, age, and coolness. As I said above, this isn't new at all, but I've never seen it used with an AJAX post like this. What's nice then is that on the server side, you can have a "proper" method without any if/else statement to see if the result was JSON. As a quick example, here is an updated version of the front end code based on the previous example. I went ahead and added jquery-json to the template to further simplify things.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="jquery.json.min.js"></script>
<script>
$(document).ready(function() {
var mydata = {data:[1,2,3,4,5,"Camden,Raymond"]};
$.post("test.cfc", {method:"handleArray",argumentCollection:$.toJSON(mydata), returnFormat:"plain"}, function(res) {
alert($.trim(res));
})
});
</script>
</head>
<body>
</body>
</html>
And as I said before, the back end CFC is now nice and simple:
<cffunction name="handleArray" access="remote" returnType="numeric">
<cfargument name="data" type="array" required="true">
<cfreturn arrayLen(arguments.data)>
</cffunction> </cfcomponent>
<cfcomponent>