Creating an Ajax Form

Ajax Contact FormWhen creating forms that need to be validated against a user's input, you can either validate on the client-side (Javascript), or the server-side (PHP in this case).
But if you want to use Javascript, then someone with Javascript turned off could easily submit the form and bypass all validation.

That's where AJAX comes in. You do all the validation on the server-side, but return the results back to the user with Javascript and no page refreshes. It's really the best of both worlds. Plus it degrades good enough if someone has Javascript disabled.

Download

View Demo

Step 1 - HTML

Let's start with the HTML layout of the form. It'll just be a simple contact form with three fields.

<div id="form">
<form id="contact" method="post" action="">
<label for="name">Your Name:</label>
<input type="text" name="name" id="name" class="input" />

<label for="email">Your Email:</label>
<input type="text" name="email" id="email" class="input" />

<label for="message">Message:</label>
<textarea name="message" id="message" rows="4" cols="40" class="input"></textarea>

<input type="hidden" name="contact" value="1" />

<p><button type="submit">Submit!</button></p>
</form>
</div>

We wrapped the form in a div for use later with the Javascript.

Step 2 - The PHP

When the form is submitted, the PHP will go validate all the fields and return a result back to the Javascript to let it know if everything went ok. If there are errors it returns a JSON encoded string with the errors.

<?php

if ( ! empty($_POST['contact']))
{
$valid = array
(
'name' => array('/^[\w\d\._\-]+$/iD', 'Your name isn\'t filled out correctly.'),
'email' => array('/^[-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?$/iD', 'You must provide a valid email.'),
'message' => array('/(.+){10,}/', 'You can\'t send a blank message.'),
);

$errors = array();

foreach ($valid as $field => $data)
{
$regex = $data[0];
$message = $data[1];

$input = trim($_POST[$field]);

if (empty($input) OR ! preg_match($regex, $input))
{
$errors += array($field => $message);
}
}

$result = empty($errors) ? 'success' : 'errors';

echo json_encode(array
(
'result' => $result,
'errors' => $errors,
));
exit;
}

?>

Alright, so first we check for the hidden field contact to make sure the form was submitted.
If it was, then we set up our validation array. So each key of the array corresponds to the form field we want to validate, and it holds another array with the Regular Expression to validate against, and also the error message to show if it fails validation.

So then we loop through the validation array and make sure each required field isn't empty, and also check it against the Regex. If it fails the Regex, then we add it to the $errors array.
The errors array is just an associative array (key => value) with the field name and the error message.

Then, we check if there are any errors, and set our $result variable to the appropriate value. We do this so the Javascript can figure out what to do with the JSON data, depending on whether the validation passed or failed.

Finally, the result and errors are echoed with the json_encode() function that Javascript will read in. And don't forget that last exit, because without it the rest of the HTML page would render and screw up our JSON output.

Step 3 - Javascript

Now we finally get to the javascript. I like the jQuery library, so we'll be using that. So let's first include the latest version of jQuery from google:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

Now here's the javascript. The comments should help explain what's going on.

/**
* Just a simple function to enable / disable our submit button
* It lets the user know we're working on the request, and something is actually happening.
*/
(function() {
$.fn.toggleButton = function() {
var $this = $(this),
disabled = $this.attr('disabled');

( ! disabled) ? $this.html('Submitting...').attr('disabled', 'disabled')
: $this.html('Send!').attr('disabled', '');

return this;
}
})();

// Shortcut to $(document).ready()
$(function() {

// Attach function to the 'submit' event of the form
$('#contact').submit(function() {
var self = $(this), // Caches the $(this) object for speed improvements
post = self.serialize(); // Amazing function that gathers all the form fields data
// and makes it usable for the PHP

// Disable the submit button
self.find('button').toggleButton();

// Send our Ajax Request with the serialized form data
$.post('index.php', post, function(data) {
// Since we returned a Json encoded string, we need to eval it to work correctly
var data = eval('(' + data + ')');

// If everything validated and went ok
if (data.result == 'success') {
// Fade out the form and add success message
$('#contact').fadeOut(function() {
$(this).remove();
$('<div class="message success"><h4>Thanks for your email!</h4></div>')
.hide()
.appendTo($('#form'))
.fadeIn();
});
}
else {
// Hide any errors from previous submits
$('span.error').remove();
$(':input.error').removeClass('error');

// Re-enable the submit button
$('#contact').find('button').toggleButton();

// Loop through the errors, and add class and message to each field
$.each(data.errors, function(field, message) {
$('#' + field).addClass('error').after('<span class="error">' + message + '</span>');
});
}
});

// Don't let the form re-load the page as would normally happen
return false;
});

});

Conclusion

So there ya go! We now have a working Ajax form.
Hopefully the code helped you out and gave you some new ideas on accomplishing this common task.


Comments

  • WGR Studio WGR Studio July 4, 2009

    Hy, anywhere a zip file?

  • Corey Worrell Corey Worrell July 4, 2009

    Just added a download link at the top!

  • Piotr Swioklo Piotr Swioklo June 4, 2010

    Hi. This form looks great!
    Exactly what I need. Simple, in one file, with validation.
    However I can't get it to work. :/
    I have tried 2 different servers and it doesn't work.
    Submit button changes to Submitting... and there is no further action...
    I have uploaded it so you can preview http://www.swioklo.com/ajax_form.php

    if you could give me any idea on what can be wrong it would be very much appreciated.

    thanks a lot

    Piotr

  • Corey Worrell Corey Worrell June 4, 2010

    @Piotr Swioklo: I would recommend installing Firebug for Firefox for future javascript debugging.

    The problem here though was my fault, this line:

    $.post('index.php', post, function(data) {

    Should be changed to this:

    $.post('ajax_form.php', post, function(data) {
  • Ricardo Ricardo July 9, 2010

    Here do I specify the recieving email?

    Thanks

  • Corey Worrell Corey Worrell July 9, 2010

    I left out the e-mail part of this tutorial. Not sure why, guess I just thought it was out of the scope of this tutorial. You will need to add in the actual code to send the email. http://php.net/mail

  • Vlad Jantuan Vlad Jantuan November 19, 2010

    Hi! Seems a clean and nice solution, but can't make it work. Even if I try to test the downloaded example on localhost or live server (on steadfast) after submitting the empty form, all it does is the button's text changes to "submitting". What could be the problem? Thanks Corey!

  • Vlad Jantuan Vlad Jantuan November 19, 2010

    Hi again! Just figured out the mistake. Everything works great. Just was wondering how do add a field that is not required, but just to be checked for regular expressions? Thanks in advance!

  • Usha Usha February 23, 2011

    Hi! I found this form the coolest one in the collection. Just what I was looking for. Works as expected. I added a php mail script to the form action attribute. It did not send mail. I then had to comment line# 63 of your JavaScript : return false;
    Then the mail goes ok, but page is redirected to mail script and hangs. Where am I going wrong? Can you please help..?

  • Qaysar Akbar Qaysar Akbar October 4, 2011

    Hello,

    Hope you can help, I wanted to know where do I put the PHP send email code. I have very limited amount of PHP knowledge.

    Any help is much appreciated

    my email is qakbar@hotmail.co.uk

    Thank you

  • asdfghjkl asdfghjkl October 29, 2011

    ASDFGH

  • asdfghjkl asdfghjkl October 29, 2011

    ASDFEGHJYKWERETYUKLO

  • Dimazz Dimazz November 28, 2011

    Hi!

    It's just great script. But it doesn't accept Russian letters (not validating them).

    I think it's somewhere in this code, but I can't get what to change there..

    'name' => array('/^[\w\d\._\-]+$/iD', 'Your name isn\'t filled out correctly.')

    And one more little problem. I want to redirect after mail sent. I tried this code, but it doesn't work :(

    if (data.result == 'success') {
    $.ajax({
    url: "http://mysite.com/thx"
    });

    What I am doing wrong?

  • Gina Gina December 1, 2011

    I've been trying for 2 days to find a form that does this and doesn't mess with my already styled contact form.
    And now, you forget the most important part of the form??
    ;)
    My search continues...

  • Corey Worrell Corey Worrell December 2, 2011

    @Gina: Hmmm, not sure what you mean. What did I leave out?

  • Eric Eric December 4, 2011

    Corey, now you are playing dumb to Gina. You are losing a lot of loyalty. I'm moving on as well.

  • Corey Worrell Corey Worrell December 4, 2011

    @Eric: Hahaha. Are you a bot?

  • ArtRayd ArtRayd December 7, 2011

    Need help!

    Everything is cool!

    Exept one thing, every time that I press on send button it sends mail, even if no fields filled. What should I do to stop mailing?

    What I have to insert before mail tag in php part of file?

    Someting like if succes - mail, if not don't mail! But how to write it, help plz!

  • Todd Lohenr Todd Lohenr December 8, 2011

    Why don't you just tell us how to make the mail part of the darned form!!

  • Corey Worrell Corey Worrell December 8, 2011

    Calm down man. You don't get what you want by yelling. And the mail part isn't in the scope of this tutorial. Did I title this post "Creating an Ajax Form and Sending an Email"? Nope.

  • nij nij December 11, 2011

    There is an error. When you press on send button it send's email in any case. even if all fields not filled

  • Dr. Awesome Dr. Awesome March 19, 2012

    Pretty stupid to not include the mail part in this tutorial. You're acting like an asshole in response to people asking for help.

  • Andrew Anderson Andrew Anderson April 14, 2012

    Hi, i really like this contact form, however like others i cant send mail. Can you tell me exactly what code to add and where. Thanks

  • Christopher Becker Christopher Becker May 31, 2012

    I get a 500 server error within the jquery tool.js not sure why, does anyone know why?

  • ale ale January 31, 2013

    Really Eric youre an asshole, sory but you cant put a tutorial and make you the Big programmer... poor boy you cant help us with sending php form.
    sorry for my english..

  • Rim Rim April 3, 2013

    how can i use this form with asp CDO mailer

  • oli oli May 10, 2013

    why would someone with no advanced coding skills would look for an ajax form that does not actually work because you could not be arsed to include the "send email" script? are ye a joker... sorry to say it, it is a nice form but it is simply useless.
    I agree with the others...

  • Plapygacy Plapygacy November 27, 2013

    ??????????????????????? '?'??? http://www.07775683.com/ norhea???????????????????????? ?????????? ??????????????????????? ?????? ???? ?????? ???????????????????? ????????? ANNA SUI ??? ?? '??'??????????????????????? ??????? m1400 ???????????????????????? ???????????????????????????????????

  • xitpnzv60 xitpnzv60 April 17, 2014

    xitpnzv60

  • mlvptus59 mlvptus59 April 17, 2014

    mlvptus59

  • designer designer April 23, 2014

    omg, how could you NOT include the part with the actual form being sent??? This tutorial is so detailed about EVERYTHING that leaving that part out is simply silly

  • nomorecrap nomorecrap May 15, 2014

    crap


Add Comment

  • (optional)