Themeforest

Create Your Own jQuery AJAX Form Submit With Validation

For today’s tutorial we are going to do something a little more interesting and take several jQuery functions, which have been covered in our previous posts and combine them to create our own form submit process, which will be able to handle all of the forms in our projects.

This is a good exercise to see how various components/snippets can be combined to create a complete function.

The tutorial assumes you have the basic understanding of the HTML and CSS for the form.

View DemoDownload Source Files

The Basic Components

So, in order to create our process we are going to use the following components:

  1. A general HTML form format
  2. Our standard CSS rules for styling the form
  3. Add default text for our input fields, including a function to remove the default text when the form is submitted – see earlier blog post – Add Default Text To Form Fields Using jQuery
  4. jQuery validation rules, which are applied when a form is submitted
  5. jQuery code for processing the form and submitting the contents via AJAX

1. HTML Form Format

Obviously everyone has their own preferences when it comes to how you code your form. After experimenting with several different formats I found that using an ordered list to handle the layout, which each form input field and associated label being one list item, has been easiest to use and so far has been robust enough to take most standard form requirements.

For the tutorial we will create a standard contact form with a name field, email, telephone and text area for comments:

<form id="form-contact" class="styled" action="/user_functions.php" method="post">
		    <fieldset>
			  <legend>Contact Form</legend>
			  <ol>
			    <li class="form-row">
				  <label>Email:</label>
				  <input id="input-email" type="text" class="text-input required email default" name="email" value="" title="Enter Your Email Address" />
				</li>
				<li class="form-row">
				  <label>Name:</label>
				  <input id="input-name" type="text" class="text-input required default" name="name" value="" title="Enter Your Full Name" />
				</li>
				<li class="form-row">
				  <label>Phone:</label>
				  <input id="input-phone" type="text" class="text-input" name="phone" value="" />
				</li>
				<li class="form-row">
				  <label>Comments:</label>
				  <textarea id="input-message" class="text-area" name="message" cols="40" rows="8"></textarea>
				</li>
				<li class="button-row text-right">
				  <input class="btn-submit" type="submit" value="submit" name="submit" />
				</li>
			  </ol>
			</fieldset>
		  </form>

As usual our jQuery will use css classes and IDs for the selectors. The key ones we need to include are:

  • Class “btn-submit” on the form submit button – used to trigger the function.
  • Class “required” on any input fields to be validated.
  • Class “email” as an additional class on those input fields to be tested against our regular expression for correctly formatted email addressed.

2. The Form CSS

The CSS I use as the basis for this format is as follows:

.styled {
font-family: Arial, sans-serif;
}
.styled fieldset {
border: 1px solid #ccc; padding: 10px;
}
.styled fieldset legend {
font-size: 16px; font-weight: bold; color: #000; text-transform: capitalize; padding: 5px; background: #fff; display: block; margin-bottom: 0; border: 1px solid #ccc;
}
.styled fieldset ol, .styled fieldset ol li {
list-style: none;
}
.styled fieldset li.form-row {
margin-bottom: 3px; padding: 2px 0; width: 100%; overflow: hidden; position: relative;
}
.styled label {
font-size: 12px; display: block; font-weight: bold; float: left; width: 100px; margin-left: 5px; line-height: 24px;
}
.styled input.text-input, .styled .text-area {
background: #fefefe; border-top: 1px solid #909090; border-right: 1px solid #cecece; border-bottom: 1px solid #e1e1e1; border-left: 1px solid #bbb; padding: 3px; width: 220px; font-size: 12px;
}
.styled input.text-input.default.active, .styled .text-area.default.active {
color: #666; font-style: italic;
}
.styled fieldset li.button-row {
margin-bottom: 0; padding: 2px 5px;
}
form input.btn-submit {
padding: 3px 7px; border: 1px solid #fff; background: #066CAA; font-size: 12px;
}

This is pretty much the minimum styling we need to add to get the labels and input fields aligned and pad/border the form. This can then be applied to your forms by adding the class “styled”. You can build on the above CSS to make your forms a little more exciting!

Any specific rules you may want to add for each form can be done using it’s id. For our contact form #form-contact, we want to set the width to 320px and center on the page.

Validation CSS

In addition to the form layout we also need a few additional CSS rules, which will handle the styling of the validation results:

.styled span.error {
font-size: 11px; position: absolute; top: 0; right: 0; display: block; padding: 2px;
}
.styled fieldset li.error {
color: #D8000C; background: #fff0f0 url(../media/images/checkers.png) repeat; border: 1px solid #f9c7c7; padding: 5px 0;
}
.styled fieldset li.error label {
text-align: left;
}

3. The jQuery Code – Default Text Function

Before we tackle the form submission and validation lets add the jQuery code to handle the default text for the input fields – See earlier post for explanation.

$(".default").each(function(){
  var defaultVal = $(this).attr('title');
  $(this).focus(function(){
    if ($(this).val() == defaultVal){
      $(this).removeClass('active').val('');
    }
  });
  $(this).blur(function() {
    if ($(this).val() == ''){
      $(this).addClass('active').val(defaultVal);
    }
  })
  .blur().addClass('active');
});

We can now add default text to any of our form fields by simply adding the class “default” and using the title attribute to hold the default text. In our contact form example we have decided to add default text to both the email fields and the name field, which are both required.

Since we dont want the default text to be submitted with the form for any empty fields we add a jQuery function, which will automatically check all input fields with class “default” and remove the text if the value is the same as the title attribute:

function defaulttextRemove(){
  $('.default').each(function(){
    var defaultVal = $(this).attr('title');
    if ($(this).val() == defaultVal){
      $(this).val('');
    }
  });
}

Now for our main function, handling the form submit. There are a few parts to this process:

  1. Check the form details – i.e. exactly which submit button has been pressed and the action URL for the data, since we are creating a generic function, which can be used by any forms, including multiple instances on one page.
  2. Run the relevant validation on all required input fields – for our example we have both standard required text field and email validation using regular expressions to check for a correct email format.
  3. Assuming no errors, we serialize the form data and using AJAX, post the contents to the form URL and return a result.

4. Form Validation and AJAX Form Submit jQuery Code

// Declare the loading gif as a variable, which will be used later
var $loading = $('<div class="loading"><img src="/media/images/loading.gif" alt="" /></div>');

// Form validation and submit when button is clicked
$('.btn-submit').click(function(e){

  // Declare the function variables - parent form, form URL and the regex for checking the email
     var $formId = $(this).parents('form');
     var formAction = $formId.attr('action');
     var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;

  // In preparation for validating the form - Remove any active default text and previous errors
      defaulttextRemove();
      $('li',$formId).removeClass('error');
      $('span.error').remove();

  // Start validation by selecting all inputs with the class "required"
      $('.required',$formId).each(function(){
          var inputVal = $(this).val();
          var $parentTag = $(this).parent();
          if(inputVal == ''){
              $parentTag.addClass('error').append('<span class="error">Required field</span>');
          }

      // Run the email validation using the regex for those input items also having class "email"
	  if($(this).hasClass('email') == true){
              if(!emailReg.test(inputVal)){
                  $parentTag.addClass('error').append('<span class="error">Enter a valid email address.</span>');
              }
          }
    });

    // All validation complete - check whether any errors exist - if not submit form
       if ($('span.error').length == "0") {
           $formId.append($loading.clone());
           $('fieldset',$formId).hide();
           $.post(formAction, $formId.serialize(),function(data){
               $('.loading').remove();
               $formId.append(data).fadeIn();
           });
      }
    // Use the following to prevent the form being submitted the standard way
      e.preventDefault();
});

When the submit button is clicked all input fields with the class “required” are checked to see if they have a value. If not an error class is applied to the parent list tag (allows us to highlight the complete form row) as well as an error text message inserted after the input field.

If the input field also has the class “email” a further validation check is made using a standard regular expression to see if the text pattern matches that of an email format.

If any of the validation checks return an error then the form submit is stopped. Here we use an extremely easy and effective way of seeing if there are any errors by using $(‘span.error’).length. If length is not “0″ then there are error messages still active.

If all validation is clear we then use the $.post function to submit the form data. At the same time we hide the form contents and replace with a loading gif.

When the data is returned from the AJAX post we then hide the loading gif and replace the form contents with the data itself – usually this would be something like a status message for the user.

The Complete jQuery Code

jQuery(document).ready(function($) {
	var $loading = $('<div class="loading"><img src="/media/images/loading.gif" alt="" /></div>');
	$(".default").each(function(){
		var defaultVal = $(this).attr('title');
		$(this).focus(function(){
			if ($(this).val() == defaultVal){
				$(this).removeClass('active').val('');
			}
		});
		$(this).blur(function() {
			if ($(this).val() == ''){
				$(this).addClass('active').val(defaultVal);
			}
		})
		.blur().addClass('active');
	});
	$('.btn-submit').click(function(e){
		var $formId = $(this).parents('form');
		var formAction = $formId.attr('action');
		defaulttextRemove();
		var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
		$('li',$formId).removeClass('error');
		$('span.error').remove();
		$('.required',$formId).each(function(){
			var inputVal = $(this).val();
			var $parentTag = $(this).parent();
			if(inputVal == ''){
				$parentTag.addClass('error').append('<span class="error">Required field</span>');
			}
			if($(this).hasClass('email') == true){
				if(!emailReg.test(inputVal)){
					$parentTag.addClass('error').append('<span class="error">Enter a valid email address.</span>');
				}
			}
		});
		if ($('span.error').length == "0") {
			$formId.append($loading.clone());
			$('fieldset',$formId).hide();
			$.post(formAction, $formId.serialize(),function(data){
				$('.loading').remove();
				$formId.append(data).fadeIn();
			});
		}
		e.preventDefault();
	});
});
function defaulttextRemove(){
	$('.default').each(function(){
		var defaultVal = $(this).attr('title');
		if ($(this).val() == defaultVal){
			$(this).val('');
		}
	});
}

View Demo

Download Source Files

10 Comments

  • I trying to create a ajax form please look at the code

    $(window).load(function() {
    
    	/* Ajax Contact form validation and submit */
    	jQuery('form#contactForm').submit(function() {
    		jQuery(this).find('.error').remove();
    		var hasError = false;
    		jQuery(this).find('.requiredField').each(function() {
    			if(jQuery.trim(jQuery(this).val()) == '') {
    				if (jQuery(this).is('textarea')){
    					jQuery(this).parent().addClass('input-error');
    				} else {
    					jQuery(this).addClass('input-error');
    				}
    				hasError = true;
    			} else if(jQuery(this).hasClass('email')) {
    				var emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
    				if(!emailReg.test(jQuery.trim(jQuery(this).val()))) {
    					jQuery(this).addClass('input-error');
    					hasError = true;
    				}
    			}
    		});
    		if(!hasError) {
    			jQuery(this).find('#born-submit').fadeOut('normal', function() {
    				jQuery(this).parent().parent().find('.sending-message').show('normal');
    			});
    			var formInput = jQuery(this).serialize();
    			var contactForm = jQuery(this);
    			jQuery.ajax({
    				type: "POST",
    				url: jQuery(this).attr('action'),
    				data: formInput,
    				success: function(data){
    					contactForm.parent().fadeOut("normal", function() {
    						jQuery(this).prev().prev().show('normal'); // Show success message
    					});
    				},
    				error: function(data){
    					contactForm.parent().fadeOut("normal", function() {
    						jQuery(this).prev().show('normal');  // Show error message
    					});
    				}
    			});
    		}
    
    		return false;
    
    	});
    
    	jQuery('.requiredField').blur(function() {
    		if(jQuery.trim(jQuery(this).val()) != '' && !jQuery(this).hasClass('email')) {
    			if (jQuery(this).is('textarea')){
    				jQuery(this).parent().removeClass('input-error');
    			} else {
    				jQuery(this).removeClass('input-error');
    			}
    		} else {
    			if (jQuery(this).is('textarea')){
    				jQuery(this).parent().addClass('input-error');
    			} else {
    				jQuery(this).addClass('input-error');
    			}
    		}
    	});
    
    	jQuery('.email').blur(function() {
    		emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
    		if(emailReg.test(jQuery.trim(jQuery(this).val())) && jQuery(this).val() != '') {
    			jQuery(this).removeClass('input-error');
    		} else {
    			jQuery(this).addClass('input-error');
    		}
    	});
    
    	jQuery('.requiredField, .email').focus(function(){
    		if (jQuery(this).is('textarea')){
    			jQuery(this).parent().removeClass('input-error');
    		} else {
    			jQuery(this).removeClass('input-error');
    		}
    	});
    
    });
    

    And HTML code for the same form

    <div class="one_third">
    
    						<h4>Get in Touch</h4>
    
    						<p class="success-sending-message">Thank you, your message has been sent!</p>
    		                <p class="error-sending-message">There has been an error, please try again.</p>
    
    		                <div id="contact-form">
    
    		                    <form action="" id="contactForm" class="styled" method="post">
    
    	                        	<label for="contact_name">Name</label>
    	                            <input type="text" tabindex="3" id="contact_name" name="contact_name" value="" class="requiredField textbox" />
    
    		                        <label for="contact_email">Email</label>
    		                        <input type="text" tabindex="4" id="contact_email" name="contact_email" value="" class="requiredField email textbox" />
    
    		                       	<label for="contact_subject">Subject</label>
    								<input type="text" tabindex="5" id="contact_subject" name="contact_subject" value="" class="requiredField textbox" />
    
    		         				<label for="contact_message">Your Message</label>
    		                       	<div class="textarea-wrap">
    		                         	<textarea cols="65" rows="9" tabindex="6" id="contact_message" name="contact_message" class="requiredField"></textarea>
    		                       	</div>
    
    		                        <div class="form-section">
    		                            <button class="button" tabindex="7" type="submit" id="born-submit" name="born-submit">Send Message</button>
    		                            <input type="hidden" name="submitted" id="submitted" value="true" />
    		                            <span class="sending-message"><img src="css/images/loading-light.gif" /> Sending...</span>
    		                        </div>
    
    		                    </form>
    
    		                </div>
    					</div>
    

    When I submitted my form, It said “Thank you, your message has been sent!” But where this message is going I don’t know. Where should i mention my email address so that it goes into that only. Please help.

    • You will need to add server-side code to handle your own email submission. If you are using PHP then you can use:

      http://php.net/manual/en/function.mail.php

      • Thanks for your quick reply.
        I’m using HTML template for my website. Can you please help me with the code ?

  • I am having some problem that is whenever i run scripts it throws error message
    Error: [Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" location: "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js Line: 127"]

    Source File: http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js

    Line: 127

    Help me

    • It may be due to the URL being used on your form with the AJAX request. Also search for the error in google to get more information on what may cause this problem with jquery

  • thanks this is a great example although i am having some trouble with submitting the form here is the handle.php script i am trying to run it through

    <?php
    $to = $_REQUEST['sendto'] ;
    $from = $_REQUEST['Email'] ;
    $name = $_REQUEST['Name'] ;
    $headers = "From: $from";
    $subject = "Example - Contact Form"; 
    
    $fields = array();
    $fields{"Name"} = "Name";
    $fields{"Email"} = "Email";
    $fields{"Phone"} = "Phone";
    $fields{"Message"} = "Message"; 
    
    $body = "We have received the following information:\n\n"; foreach($fields as $a => $b){ $body .= sprintf("%20s: %s\n",$b,$_REQUEST[$a]); } 
    
    $headers2 = "From: noreply@example.com";
    $subject2 = "Thank you for contacting us";
    $autoreply = "Thank you for contacting us. Somebody will get back to you as soon as possible. If you have any more questions, please consult our website at http://www.example.com";
    
    if($from == ''):
    	print "You have not entered an email, please go back and try again";
    elseif($from == 'your@email.com'):
    	print "You have not entered an email, please go back and try again";
    elseif($name == ''):
    print "You have not entered a name, please go back and try again";
    elseif($name == 'Name'):
    print "You have not entered a name, please go back and try again";
    else:
    $send = mail($to, $subject, $body, $headers);
    $send2 = mail($from, $subject2, $autoreply, $headers2);
    endif;
    if($send)
    {header( "Location: http://example.com/thankyou.htm&quot; );}
    else
    {header( "Location: http://example.com/error.htm&quot; );}
    ?>
    

    and the form is pretty much the same just with different css styling

     <form id="form-contact" class="styled" action="http://example.com/inc/handle.php&quot; method="post">
    		    <fieldset>
    
    			  <ol>
    			    <li class="form-row">
    				  <label>Email:</label>
    				  <input id="input-email" type="text" class="text-input required email default" name="Email" value="" title="Enter Your Email Address" />
    				</li>
    				<li class="form-row">
    				  <label>Name:</label>
    				  <input id="input-name" type="text" class="text-input required default" name="Name" value="" title="Enter Your Full Name" />
    				</li>
    				<li class="form-row">
    				  <label>Phone:</label>
    				  <input id="input-phone" type="text" class="text-input" name="Phone" value="" title="Enter Your Phone Number" />
    				</li>
    				<li class="form-row">
    				  <label>Enquiry:</label>
    				  <textarea id="input-message" class="text-area" name="Message" cols="40" rows="8"></textarea>
    				</li>
    				<li class="button-row text-right">
                                      <input type="hidden" name="sendto" value="sales@example.com"/>
    				  <input class="btn-submit" type="submit" value="submit" name="send" />
    				</li>
    			  </ol>
    			</fieldset>
    		  </form>
    

    as far as the jquery is concerned i have not modified it from the original any help you could give me would be appreciated.

    when jquery validates the information the form just vanishes and dosen’t seem to post the data to the server as echo requests display no information eg echo $_REQUEST ['Name'] ; dose not return anything.

    and once again thanks for this example I’m beginning to understand jquery little by little

    • Hi,

      Try changing $_REQUEST to $_POST

      • thanks for the quick reply i seemed to have solved it there was a couple of typos eg non capital name attributes when they should have been capitalized $_REQUEST is better to use then $_POST as it allows you to grab info from both post and get requests so i can reuse the same script for different forms i have solved the issues i had.

        on a different note it appears to ignore the header redirects within the .php script so i will need to think of another method to redirect after the form has been submitted as window.location doesn’t seem to work either.

        i may have to read the documentation on jquery to solve this one… however the form is passing the information correctly after i implemented an AJAX function to solve it temporarily however it is no longer required as the jquery script works flawlessly thanks again for this tutorial it was quite helpful.

  • I want to create menu under each post – Men, Women, Kids, etc. How do I do this. At the monent I just get the option to add menu to Home page though widget. I want to add menu to each post that I have created

    • Hi Anj – If this is for one of the WordPress plugins then you first need to create a menu in the admin custom menu area. You can then assign this to the relevant plugin via the widget control panel

Leave a comment

To add code to your comments wrap the code text in [text][/text] tags