views:

94

answers:

3

I need to return multiple values from a ColdFusion function in an ajax callback function. Here's what I've got:

$('input[name="StateName"]').live('change', function() {
    var StateID = $(this).parents('tr').attr('id');
    var StateName = $(this).val();
    $.ajax({
        url: 'Remote/State.cfc'
        ,type: "POST"
        ,data: {
            'method': 'UpdateStateName'
            ,'StateID': StateID
            ,'StateName': StateName
        }
        ,success: function(result){
            if (isNaN(result)) {
                $('#msg').text(result).addClass('err');
            } else {
                $('#' + result + ' input[name="StateName"]').addClass('changed');
            };
        }
        ,error: function(msg){
            $('#msg').text('Connection error').addClass('err');
        }
    });
});

If I trap a database error, then the success callback is fired, and the result is Not a Number (It is in fact, the text of the error message). I need the function to also pass back other values. One might be the primary key of the row that caused the error. Another might be the old StateName, so that I can refresh the old value on the screen so that the client will know absolutely for sure that their change did not take effect.

I guess I'm breaking the rule of atomicity here and need to fix that, because I'm using result as both the primary key of the row that was updated, or it's the error message if the update fails. I need to return both the primary key and the error message.

+4  A: 

I make all my ajax requests return the same object type. The pattern I use is a pretty common one - my response object always consists of a Success flag, a Data property, and an Errors collection.

If you jsonify an object like that and return it for all your ajax requests, you can always determine if the request was successful, what the errors were (if any), and if it was successful, you'll have the resulting data. In this way, you'll always be able to handle your responses in a consistent manner.

Note that the Errors collection would be business logic errors - actual server errors would still trigger the jQuery failure handler. But using the above object, your "success" function looks more like:

 if (!result.Success) {
    $('#msg').text(result.Errors[0]).addClass('err');
 } else {
    $('#' + result.Data + ' input[name="StateName"]').addClass('changed');
 };
womp
+1 for having a consistent convention
Antony
+6  A: 
Pascal MARTIN
Thanks Pascal Martin! OK, I've changed the result to be:{"STATEID":101.0,"MSG":"Hello World"}, but now how do I address result.msg? Is it result.DATA.msg or something?
cf_PhillipSenn
You're welcome :-) As you are using jQuery, you should take a look at http://api.jquery.com/jQuery.ajax/ ; the `dataType` option looks interesting, as you can set it to `json` ; and, then, your `success` callback should directly receive a Javascript object ;; which would me something like `result.STATEID`, `result.MSG`, ...
Pascal MARTIN
Yeah, I was using result.msg when I should have been using result.MSG.Arg! Whoever rationalized having a computer language that was case sensitive? Don't they know it's all 1's and 0's!!
cf_PhillipSenn
Well, let's feel happy we don't use uppercase 1s and 0s :-p
Pascal MARTIN
+1  A: 

You can return xml string and then access it in success function:

success:function(data)
{
  var err_code,err_msg;
  //read err_code and err_msg:
  // we need 2 different handlers for IE and all other browsers.
            if (! $.browser.msie) 
            {
                // this code surprisingly doesn't work with IE.
                err_code = $('error_code:first',data).text();
                err_msg = $('error_message:first',data).text();
            }
            else
            {
                var xml = new ActiveXObject("Microsoft.XMLDOM");
                xml.async = false;
                xml.loadXML(data);
                err_code = xml.documentElement.getElementsByTagName('error_code')[0].text;                    
                err_msg = xml.documentElement.getElementsByTagName('error_message')[0].text;
            }

}
a1ex07