How do I use ajax with Framework X?

One of the easiest ways to spot someone who is still new to programming web applications is to read the question, "How do I submit an ajax form with Framework X"

How can I say that, when I don't even know which framework they are talking about? Exactly - because, the backend language & framework is irrelavent, and that's the key to understanding that they are still missing a fundamental understanding of this really rather simple process.

So let's fix that problem - not by providing another follow-along tutorial you can copy & paste, but by looking at some broken code and figuring out how to fix it!

I'm going to make use of Gist a lot in this post to try to make the code easier to set up. You will also need to use Firebug, or a similar tool that will give you the same basic information we'll use to debug. Here is our starting, broken code - place them both in a web directory called "ajax_tut"

Set up those two files and navigate to http://localhost/ajax_tut/form.html. You will see a typical boring form asking you to type in your name & submit it. When you do, you should see a typical, boring "Hello, X" message returned. Go ahead and try that now.

What? Nothing? It isn't working? Well...you're a programmer - let's find out why not.

Pop open your Firebug console and try to submit again. Ouch! Ugly red warnings! Let's see what they are telling us:

POST http://localhost/submit.php  404 Not found

//click on that and then the Response tab:

The requested URL /submit.php was not found on this server.

Ok, simple enough - we've used the wrong relative path to submit to our backend.

// We'll change
url: '/submit.php',

// to be 
url: 'submit.php',

Refresh the page, test again, and... Nothing. Okay, well - pop open our Firebug again, submit once more and see what the error is.

Now we've started to hit the meat of this lesson. There is no error message. So what are we doing wrong? The key is still there in Firebug, if you look carefully. Remember our response tab from last time? It's missing! If we don't have a response from our form, how can we possibly post it to the page? Time to switch to our submit.php file

Now, at the top of this article I said that it didn't matter what language or framework you use. The only things that really matter are that you have a reachable endpoint and provide a response (Why did he just call it an endpoint? Isn't that just for apis? Learn why ).

Our response isn't working, so let's fix that.

// We'll change
return $message;

// to be 
echo $message;

Hooray! A response...and another ugly error, and no message on the page:

SyntaxError: JSON.parse: unexpected character

Tattoo that message on your brain - you're going to see it a lot! Fortunately, it's nearly always the same issue, and easily fixed.

Despite the the name XMLHttpRequest, nearly all of this type of code is written using json to pass data back and forth. Jquery's .ajax function will handle setting that up correctly for you, if you use data: with those {} brackets (or just use form.serialize()). We wrote our own code to process the response, with var response_obj = jQuery.parseJSON(r.responseText);. But...we aren't sending back json from our server!

That is the single biggest error I see in this area, especially once people jump into frameworks and try to write the code the same way they are accustomed to doing for normal forms. This is where working with ajax is just a little bit different - but fortunately, quite easy to get used to. Just remember these 2 rules:

Rule #1 - JSON in, JSON out. 

// Replace:
return $messsage 

//with 
echo json_encode(array('message'=>$message));  

Look at your response tab in Firebug. You see a json string that looks like your array? That's what we are after. In a moment we'll learn how to grab that message and put it on our page. But first, let's also return whether or not there is an error.

//change your function to:

function submit_form($post)
{
	//dummy function - we want to return messages for our tutorial is all
	if ($post['name'] == '') 
	{
		echo 'Error';
		return 'Hey, blanky! Type your name';
	}
		
	echo 'Success';
	return 'Hello, ' . $post['name'];
} 

Darn! There's that error message again...wait! We didn't json_encode it! Try:

//change your function to:

function submit_form($post)
{
	//dummy function - we want to return messages for our tutorial is all
	if ($post['name'] == '') 
	{
		echo json_encode('error'=>'Error');
		return 'Hey, blanky! Type your name';
	}
		
	echo json_encode('error'=>'Success!');
	return 'Hello, ' . $post['name'];
} 

Aw, jeez! Now what happened? You broke rule #2:

Rule #2 - Use 1 - and only 1 - response. 

// So, we simply need to combine everything into an array FIRST, then encode & return

$message = submit_form($_POST);
echo json_encode($message); //$message is now an array

function submit_form($post)
{
	// lots of ways to do this - I like to set up all keys as being in error, then overwrite if okay
	$retval = array('error'=>'Error', 'message'=>'Unknown error');

	if ($post['name'] == '') 
	{
		$retval['message'] = 'Hey, blanky! Type your name';
		return $retval;
	}

	$retval['error'] = 'Success!';
	$retval['message'] = 'Hello, ' . $post['name'];
	return $retval;	
} 

Refresh, submit and...oh, man! Are we still having problems? I thought you said this was easy? Why is it calling me Blanky when I typed my name in?

It is easy, and we are all set on the server side, but we need to fix our form code a little bit now. Look at Firebug again, but at the Post tab this time. You can see here exactly what is being posted to your php page - in this case, "name=" nothing. Hmmm... Let's add console.log(name); directly above .ajax(... and submit again.

"(an empty string)" A-ha! We got so hung up on the fancy stuff, we looked right past the basics. Above our console.log(), write var name = $('#name').val();, refresh and submit...and it completely blows up. I hate computers.

No, you don't - let's just take look. We're getting that Syntax Error again, but by now we know it just means the response has some unexpected strings in it - Wow! Just like the message says! Firebug's Post tab is completely empty, and the Response is telling us "Undefined index: name" - wait a minute, that's just a php error causing all of this. Why isn't "name" being sent? Checking our form, we notice the old "trying to grab an element by id when only the name attribute is set" error, and quickly add id="name" to our form.

Lastly, let's get that stupid message on the page. Remember, json objects are just glorified, flattened arrays

complete: function(r){
var response_obj = jQuery.parseJSON(r.responseText);
$('#message').html(response_obj.message);
},

Break out the Champagne, boys - We made it!

Contact me