Handling JSON Responses with Prototype Version < 1.5.1
February 17th, 2009One of the pitfalls with submitting form data on the web is that control leaves the current page and the developer is responsible for rendering the form with its data in the event of a system or validation error. There’s a number of techniques to overcome this arduous task. One such technique involves never leaving the page containing the form. An asynchronous JavaScript request can be made to submit the form data. One of the client-side JavaScript libraries that does this is prototype.js.
Which brings me to this: Versions of prototype.js prior to 1.5.1 do not automatically transform JSON header responses as JavaScript objects as it does not support encoding and decoding JSON, but there is a way of working around this limitation described below. Oh, JSON is a way of representing a JavaScript object as a string.
So, given a HTML page that makes an asynchronous request. Assume onHtmlAction is added to an HTML form button when it’s clicked.
function onHtmlAction() {
var ajax_parms = $H({ target_action: 'do_something',
parm1: 'value1',
parm2: 'value2'
});
var ajax_call = new Ajax.Request('target_page.php', {
method: 'post',
parameters: ajax_parms.toQueryString(),
evalScripts: false,
onSuccess: onSuccessHandler
});
}
A POST request is made to target_page.php. Instead of returning a HTTP header with a JSON string response, print (echo) the JSON string to the response output.
<?php
echo('{ "SUCCESS" : "true" }');
?>
{ "SUCCESS" : "true" } is a JavaScript object containing a property, SUCCESS, with the string value, true. If this object was stored as a JavaScript object, anObject, I could do alert(anObject.SUCCESS); and it would display true.
When the response is received, it’s handled by a custom handler. Usually, I look for the JSON object in the second argument of the custom handler, but the value in this argument is undefined in early versions of prototype–even if when I return it as a response header. This seems to be the workaround.
function onSuccessHandler(transport, json) {
if ((json == undefined) && (transport != undefined)) {
try {
// Transform the JSON string as a JavaScript object
json = eval('(' + transport.responseText + ')');
}
catch (e) { }
}
if (json != undefined) {
// Now, use the JSON object
}
}