Submitting a form without reloading the page using jQuery and AJAX

15th February 2010


Submitting a form without reloading the page using jQuery and Ajax
In this tutorial I'll show you how to submit a form without reloading the page using jQuery and AJAX. Adding this kind of functionality to your forms will improve the user experience for your visitors as they won't need to sit and wait for the entire page to reload when the form is submitted.

Here is a demo of the jQuery AXAJ Form we're going to build in this tutorial and if you would like to you can also download a zip file containing all the files.

The HTML Form

Let's start by creating the HTML form. Below is the code that I have used for this tutorial.

<div id="contactForm" class="contactForm">
	<h1>Contact form</h1>
	<form action="php/submit-form.php" method="post">
		<ul>
			<li>
				<label for="name">Name *</label>
				<input type="text" name="name" id="name" class="txtFld" />
				<span id="errorName" class="formError"></span>
			</li>
			<li>
				<label for="email">Email *</label>
				<input type="text" name="email" id="email" class="txtFld" />
				<span id="errorEmail" class="formError"></span>
			</li>
			<li>
				<label for="subject">Subject</label>
				<input type="text" name="subject" id="subject" class="txtFld" />
				<span id="errorSubject" class="formError"></span>
			</li>
			<li>
				<label for="message">Message *</label>
				<textarea name="message" id="message" cols="30" rows="5" class="txtAra"></textarea>
				<span id="errorMessage" class="formError"></span>
			</li>
			<li>
				<input type="submit" value="Send" class="submit" id="submit" />
				<span id="formProgress" class="formProgress"></span>
			</li>
		</ul>
	</form>
</div>

Notice that I have added span tags with IDs after each text-field and one after the submit button. We'll need these for error messages so don't leave them out. The rest of it is a straight forward form marked up in an unordered list with its action set to submit-form.php and method set to post.

Once we have the HTML in place we need to style it using CSS. I'm not going to walk you through this step as you can style it as you wish. If you would like to see the styles I created for the form you can download the zip file above.

The PHP

We'll need two separate PHP files, one for the AJAX call and one which will process the form if JavaScript is disabled. This way we ensure that the form works fine even for the low percentage of people surfing with JavaScript turned off. For the purpose of this tutorial I've made both these files identical but you can, and really should, change the "non-ajax" PHP script, submit-form.php, to handle the process better than just outputting text on an empty page.

Here is the PHP code we need for the AJAX call. I've saved this code in a file named submit-form-ajax.php

<?php
if(empty($_POST['name']) || empty($_POST['email']) || empty($_POST['message'])) {
	die('Error: Missing variables');
}
$name=$_POST['name'];
$email=$_POST['email'];
$subject=$_POST['subject'];
$message=$_POST['message'];
$to='your@email.com';
$headers = 'From: '.$email."\r\n" .
	'Reply-To: '.$email."\r\n" .
	'X-Mailer: PHP/' . phpversion();
$subject = $subject;
$body='You have got a new message from the contact form on your website.'."\n\n";
$body.='Name: '.$name."\n";
$body.='Email: '.$email."\n";
$body.='Subject: '.$subject."\n";
$body.='Message: '."\n".$message."\n";
if(mail($to, $subject, $body, $headers)) {
	die('Mail sent');
} else {
	die('Error: Mail failed');
}
?>

The first few lines of code are an if statement to ensure that the name, email and message fields weren't left blank by the user. If any of them are blank the script will terminate and output an error.

After that we are assigning the values of the fields to variables ($name, $email, $subject and $message) for easier use later in the script.

In the line after that we set a variable called $to. It's value is the email address where we want the form sent.
Note: Don't forget to change your@email.com to your email address.

After that we are simply setting the values for the subject and body of the email.

In the last few lines we are using PHP's mail function in an if statement. Now if the email is sent the script will output the message "Mail sent" or else, if it fails, it will terminate and output an error message. We'll be making use of the "Mail sent" message later on in our jQuery AJAX call.

The jQuery & AJAX

Now lets get to the jQuery and AJAX part of this tutorial. We'll be using jQuery to display messages to the user, validate the form on the client side and to submit the data using AJAX.

Below is the jQuery code I have written to do all of the above. It might look like quite a bit but don't worry I'll walk you through it.

$(document).ready(function() {
	$('#contactForm #submit').click(function() {
		// Fade in the progress bar
		$('#contactForm #formProgress').hide();
		$('#contactForm #formProgress').html('<img src="images/ajax-loader.gif" /> Sending&hellip;');
		$('#contactForm #formProgress').fadeIn();	
		// Disable the submit button
		$('#contactForm #submit').attr("disabled", "disabled");
		// Clear and hide any error messages
		$('#contactForm .formError').html('');
		// Set temaprary variables for the script
		var isFocus=0;
		var isError=0;
		// Get the data from the form
		var name=$('#contactForm #name').val();
		var email=$('#contactForm #email').val();
		var subject=$('#contactForm #subject').val();
		var message=$('#contactForm #message').val();
		// Validate the data
		if(name=='') {
			$('#contactForm #errorName').html('This is a required field.');
			$('#contactForm #name').focus();
			isFocus=1;
			isError=1;
		}
		if(email=='') {
			$('#contactForm #errorEmail').html('This is a required field.');
			if(isFocus==0) {
				$('#contactForm #email').focus();
				isFocus=1;
			}
			isError=1;
		} else {
			var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
			if(reg.test(email)==false) {
				$('#contactForm #errorEmail').html('Invalid email address.');
				if(isFocus==0) {
					$('#contactForm #email').focus();
					isFocus=1;
				}
				isError=1;
			}
		}
		if(message=='') {
			$('#contactForm #errorMessage').html('This is a required field.');
			if(isFocus==0) {
				$('#contactForm #message').focus();
				isFocus=1;
			}
			isError=1;
		}
		// Terminate the script if an error is found
		if(isError==1) {
			$('#contactForm #formProgress').html('');
			$('#contactForm #formProgress').hide();	
			// Activate the submit button
			$('#contactForm #submit').attr("disabled", "");
			return false;
		}
		$.ajaxSetup ({  
			cache: false  
		});
		var dataString = 'name='+ name + '&email=' + email + '&subject=' + subject + '&message=' + message;  
		$.ajax({  
			type: "POST",
			url: "php/submit-form-ajax.php",
			data: dataString,
			success: function(msg) {
				// Check to see if the mail was successfully sent
				if(msg=='Mail sent') {
					// Update the progress bar
					$('#contactForm #formProgress').html('<img src="images/ajax-complete.gif" /> Message sent.').delay(2000).fadeOut(400);
					// Clear the subject field and message textbox
					$('#contactForm #subject').val('');
					$('#contactForm #message').val('');
				} else {
					$('#contactForm #formProgress').html('');
					alert('There was an error sending your email. Please try again.');
				}
				// Activate the submit button
				$('#contactForm #submit').attr("disabled", "");
			},
			error: function(ob,errStr) {
				$('#contactForm #formProgress').html('');
				alert('There was an error sending your email. Please try again.');
				// Activate the submit button
				$('#contactForm #submit').attr("disabled", "");
			}
		});
		return false;
	});
});

OK, lets start with the first line of code, $(document).ready(function() {. This is jQuery's handy little function to make sure that the rest of our script is run only once the document has loaded. So, basically, we want all our functions inside this jQuery function.

On the second line, $('#contactForm #submit').click(function() {, we are binding an event to the submit button which is referenced by its ID, submit. Inside this function we write the code that is to be executed once the form is submitted.

In the next three lines of code we are displaying a message to the user letting them know that the form is being processed. First we hide the progress bar with $('#contactForm #formProgress').hide();. Next we add our message to it with $('#contactForm #formProgress').html('<img src="images/ajax-loader.gif" /> Sending…'); and lastly we fade it in with $('#contactForm #formProgress').fadeIn();.

We want to disable the submit button whiles the form is being submitted just to make sure the user doesn't submit it twice. The line $('#contactForm #submit').attr("disabled", "disabled"); takes care of that for us.

The next line, $('#contactForm .formError').html('');, hides any previous error messages.

Now we're ready to start validating the user's inputs. So the first thing we'll do is create two variables that we'll use in the script for validation. The line var isFocus=0; creates and sets the value to "0" for the first of the two variables. We'll use this variable to help us keep track of which input field to set focus on if there is a validation error. The next line, var isError=0;, creates the second variable we need. We'll use this variable to see if there has been a validation error so we can stop the form from submitting and display the necessary errors.

To validate the user's inputs we need to pull the data from the form so that's what we do in the next four lines, get the user's inputs and store them in variables. var name=$('#contactForm #name').val();, var email=$('#contactForm #email').val();, var subject=$('#contactForm #subject').val(); and var message=$('#contactForm #message').val();.

Alright, it's now time to validate our first field and that's what we are doing in the following block of code…

if(name=='') {
	$('#contactForm #errorName').html('This is a required field.');
	$('#contactForm #name').focus();
	isFocus=1;
	isError=1;
}

First we are checking if the user has left the "Name" field empty, if(name=='') {, since this is a required field that would result in a validation error. If the field is empty we display an error after the input field in the form with $('#contactForm #errorName').html('This is a required field.'); and set the focus to that field with $('#contactForm #name').focus();. Since we have set focus to a field we update the value of the isFocus variable to "1". Now we can check this variable when we validate the next field and only set focus to that field, if there is an error, if isFocus is "0" because if it's "1" that would mean we have already set focus on a field and don't want to change it. We also set isError to "1" if there is an error so we later can stop the script from submitting the form.

Next lets look at the code that will validate the "Email" field. This block of code is bigger than the previous one as we'll also be checking to see if isFocus has been updated as well as if the user has entered a valid email address.

if(email=='') {
	$('#contactForm #errorEmail').html('This is a required field.');
	if(isFocus==0) {
		$('#contactForm #email').focus();
		isFocus=1;
	}
	isError=1;
} else {
	var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
	if(reg.test(email)==false) {
		$('#contactForm #errorEmail').html('Invalid email address.');
		if(isFocus==0) {
			$('#contactForm #email').focus();
			isFocus=1;
		}
		isError=1;
	}
}

So, the first line, if(email=='') {, checks if the "Email" field is empty and then if it is the second line, $('#contactForm #errorEmail').html('This is a required field.');, displays an error message after the input field in the form, same as we did with the "Name" field. If the "Email" field is empty we also check the value of isFocus on the next line, if(isFocus==0) {, and only change the focus to the "Email" field if its value is "0" with $('#contactForm #email').focus();. On the line after that, isFocus=1;, we set the value of isFocus to "1". Next we update isError and set it to "1".

So far we have checked if the "Email" field is empty and done the needful if it is. Now we need to validate the data in the "Email" field if it's not empty and make sure it's a valid email address. That is what we do in the else statement. First we create a variable called "reg" and store the regular expression in it, var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;. Next we test the value of the email variable against the regular expression in the reg variable, if(reg.test(email)==false) {, and display an error if it's not a match, $('#contactForm #errorEmail').html('Invalid email address.');. Then we do the same check for focus as earlier and set isError to "1".

The last field we need to validate is the "Message" text box. So we check if it is empty with if(message=='') { and display an error message with $('#contactForm #errorMessage').html('This is a required field.'); if it is. Then we do the check for isFocus and update isError just like we did for the previous two fields.

Now we are done checking and validating all the required input fields of the form.

The next step is to determine whether there have been any validation errors. We'll use our handy isError variable to do this check. We know that we have an error if the value of isError is "1" so we'll check that in an if statement and stop the script from submitting the form if that is the case. Lets have a look at the code we are using for this…

if(isError==1) {
	$('#contactForm #formProgress').html('');
	$('#contactForm #formProgress').hide();
	$('#contactForm #submit').attr("disabled", "");
	return false;
}

So, our if statement checks if isError is "1", if(isError==1) {, and if it is it will clear and hide the progress bar, which so far has been displaying the message "Sending…", with the lines $('#contactForm #formProgress').html(''); and $('#contactForm #formProgress').hide();. Then we activate the submit button with $('#contactForm #submit').attr("disabled", ""); and finally we stop the script from continuing with return false;.

Alright, so we have now validated all the fields and stopped the script if there are any errors. Next step is to submit the form with AJAX if there aren't any errors, so lets get to it.

One thing I like to do is use jQuery's $.ajaxSetup function to set default settings for AJAX calls. In this function we'll set "cache" to "false" which will force the pages that we request to not be cached by the browser.

$.ajaxSetup ({
	cache: false
});

That's it, now all future AJAX calls will have this setting. Below is our AJAX call to submit the form.

var dataString = 'name='+ name + '&email=' + email + '&subject=' + subject + '&message=' + message;  
$.ajax({
	type: "POST",
	url: "php/submit-form-ajax.php",
	data: dataString,
	success: function(msg) {
		if(msg=='Mail sent') {
			$('#contactForm #formProgress').html('<img src="images/ajax-complete.gif" /> Message sent.').delay(2000).fadeOut(400);
			$('#contactForm #subject').val('');
			$('#contactForm #message').val('');
		} else {
			$('#contactForm #formProgress').html('');
			alert('There was an error sending your email. Please try again.');
		}
		$('#contactForm #submit').attr("disabled", "");
	},
	error: function(ob,errStr) {
		$('#contactForm #formProgress').html('');
		alert('There was an error sending your email. Please try again.');
		$('#contactForm #submit').attr("disabled", "");
	}
});

First we're creating a variable called dataString in which we are storing our parameters. We'll use this soon in our AJAX call. Once our parameters are setup we use jQuery's $.ajax function to make our AJAX request. Inside this function we set the request method to "post" with type: "POST" and the URL we want to request with url: "php/submit-form-ajax.php". Next we pass our parameters with data: dataString where dataString is the variable we created earlier.

The next setting is success in which we create a function telling jQuery what to do if the request is successful. The function gets an argument passed back which is the data returned from the script we called. In the function we check if the data returned is the string "Mail sent" with if(msg=='Mail sent') { and if it is we update the progress bar to display the message "Message sent." with the line $('#contactForm #formProgress').html('<img src="images/ajax-complete.gif" /> Message sent.').delay(2000).fadeOut(400);. The message stays on the screen for two seconds and then fades out, delay(2000) "pauses" the script for 2 seconds and fadeOut(400) fades out the message in 400 milliseconds. We also clear out the "Subject" text field and the "Message" text box in the form, so the user can't send a second message with the same values, with the lines $('#contactForm #subject').val(''); and $('#contactForm #message').val('');.

If the data returned is not "Mail sent" that would mean we had an error. If that is the case we clear the progress bar with $('#contactForm #formProgress').html('');, and show the user an error, alert('There was an error sending your email. Please try again.');.

The next line, $('#contactForm #submit').attr("disabled", "");, enables the submit button again.

The last setting we need for the AJAX call is error. Here we create a function that tells jQuery what to do if the AJAX request wasn't successful. We'll do the exact same thing as above, clear the progress bar, display an error message to the user and then enable the submit button.

The last line of code that we need is return false; which stops our form from being submitted the traditional way.

The End

That's it, we're done. I hope you enjoyed this tutorial and learned a trick or two. If you're unclear about anything you can leave a comment below and I'll do my best to explain.

Did you enjoy this post?

If you enjoyed this post you can subscribe to my RSS RSS feed to know when I post another article. It would also be great if you bookmarked this post on your favorite social bookmarking site, if you have signed up with any.



Comments

  • Candy said:

    Hi,

    Thank you for sharing. I lIke it.

Leave a comment