2010
07.24

Again another long time between posts, this one is partly a small tutorial and partly about a small issue I encountered and workaround. This post discusses form validation using a cool jQuery form validation plugin created by Jörn Zaefferer, which I highly recommend, you can download the plugin from here. The plugin allows you to quickly and easily validate your html forms using the power of jQuery, the basic principle is that you specify the rules for validation on the fields of your form and submitting the form will be disabled until all fields are valid, where validation rules are broken the user is informed with messages next to the invalid fields. I wouldn’t be surprised if this plugin became part of jQuery directly since so many people are using it already.

Lets have a look at a quick simple example, lets say I have a form with 3 input fields, name, email and website, we want to have the name and email fields required, we want to check the email is valid and because we are storing these fields in a database with a character limit we need to check the fields are not too long. Below is the html form code and the javascript for the validation.

[code lang=”javascript”]

[/code]

In the above example you can see that you can apply the validation rules both in javascript and also using the predefined rule names as the css class for the input. E.g. the email input field is using classes email and required, the validation plugin will look for any class names on the inputs and apply the validation rule if there is one. I could have defined the email rule solely in the script but I wanted to show that there is a quicker way using classes. The working example for the above code is below.

You can also do remote validation. For example, lets say in our example we did not want someone with the same email address to be subscribed twice. You can use a special validation rule remote which points to a script which should output true or false based on the form input value. We will also give a special message for when the email address is already in use. The changed script code is then:

[code lang=”javascript”]

[/code]

The running example now will not allow you to enter the email test@example.com, for this example there is a script called check_subscribed.php which is hard coded to look for the POST email variable and return false if it equals test@example.com.

So that is all good everything seems to be validating fine. Now I will show you a small case to watch out for. Lets assume that the subscribe form needs to be submitted using ajax and only accepts a required email address which should be remotely validated. Below is the code and the working example, if you simply enter the already subscribed email test@example.com and submit you see it does not work properly, the form gets submitted even though the validation fails.

Update 29/09/2010 since updating this post and rechecking the code it appears, this actually does work. Perhaps the browsers have changed the order the javascript events occur, I certainly did not change anything, this was an issue previously.

Code and example below.

[code lang=”javascript”]

[/code]

The reason the above example did not work properly is because the remote validation checking is done asynchronously, as is the ajax request. In the above code, the form submit event binding function checks first if the form is valid before doing the ajax submit. The trouble is that the remote validation is done asynchronously. So the valid check is just returning true instead of false. In order to solve this the remote validation needs to be done synchronously instead (or async: false). Below is the relevant fix and the fixed example.

[code lang=”javascript”]
$(“#subscribe_test3”).validate({
rules: {
email: {
maxlength: 32, remote: { url: “/check_subscribed.php”, async: false }
}
},
messages: {
email: { remote: “Already subscribed”}
}
});
[/code]

Update 27/09/2010

It has been asked what the check_subscribed.php script did, so here it is below:

[code lang=”php”]
< ?php $email = $_REQUEST["email"]; if ($email == "test@example.com"){ echo "false"; } else { echo "true"; } ?>
[/code]

Update 01/11/2010

Someone has asked for the files used in these examples, so here is a zip file containing a html page and the necessary php scripts. The jquery and validation plugin are not included in the zip but are referenced as external scripts. This is a recommended way of including jQuery in your sites (but obviously a more up to date version).

66 comments so far

Add Your Comment
  1. Nice tutorial…
    but i have a problem with the remote validation

    how’s the check_subscribed.php should be..?
    help please 🙂

  2. its fine for adding a new record but how to use for update the record

  3. That’s a php question I guess. It completely depends on what your requirements are. The script above used hard-coded true or false responses, but in reality you would check your database to see if the email was already taken by querying by the email address. If you find any records you would return false. If you are editing an existing record you probably need an additional check that the email address doesn’t belong to the record you are attempting to edit.
    The remote URL can take query parameters so you could send the record id to the server to validate the email. You can also specify a POST data for the remote validation e.g.
    remote: { url: “/check_subscribed.php”, async: false, data: { id: “1”, usergroup: “2” } }

  4. hi it is very nice tutorial and i was searching it.but my jquery files are not supporting this tutorial so it will be great if you can create a downloadable zip file of this tutorial.
    i am waiting for your response,Thanks a lop

  5. great post, thanks for sharing

  6. Hi thanks for the great tutorial.
    I have another similar scenario with a twist.
    I have a field called title, with a remote check that checks for similar titles in the database.
    It works perfectly like you did it in here. And it shows the error message too. However, I actually just want to show the error message or warning, and still be able to submit the form even tho this validation failed.
    I want to allow same titles, but just show a warning to the user when he is doing so.
    Do you know how I can go about doing this?

    Thank you

  7. Hmmm, just checking the documentation for the validation plugin, it appears you can set your own form submit function, which I suppose you could check whether the form or individual elements were valid and then submit the form anyway. See here http://docs.jquery.com/Plugins/Validation#General_Guidelines it advises to use this:
    [code lang=”javascript”]
    $(“#myform”).validate({
    submitHandler: function(form) {
    form.submit();
    }
    });[/code]
    You can validate individual elements programatically using:
    [code lang=”javascript”]
    $(“#myform”).validate().element( “#myselect” );[/code]

    So in the submit function you could make the sure the errors/warnings are displayed and then use the native form submit function to submit it anyway. Hope that helps.

  8. Download file don’t exist any more!

  9. Thanks for letting me know, the download link is working again.

  10. Thanks for this detailed tutorial, it got me up and validating in a flash!

    I found one anomaly, however, that I hope you can help with. Using the code below, it seems that no standard email type validation is occurring before performing the ajax request. This results in all error messages stating that the user already exists, rather than identifying a mis-formed address.

    So, whether the user types jimmy@micros, jjj.micros, or any other invalid address, the ajax call is performed, and the user is warned that the email has already been registered. So, in a nutshell, Is there a way to perform standard validation BEFORE the ajax request?

    email: { required: true, email: true, minlength: 3, remote: “checkemail.php” , async: false },

    Thanks again for your quick and easy to follow post!

  11. Jim, thanks for the nice comments. I believe you might be referring to the issue identified in the post. I noticed that this would happen to me when I filled in a form with an email address field that required remote validation and pressed the form submit button immediately without leaving the focus of the email field.

    It appears that the default functionality of the validation is to validate when focus leaves the field. When you press the submit button focus does leave the field, but since the remote validation is done asynchronously, the form is incorrectly validated as correct and submitted at around the same time as the remote validation check.

    The async parameter should fix this, but I think in your case you might need to put the async: false as a parameter of the remote section, rather than the email rule. Try and replace your email rule with this instead:
    [code lang=”javascript”]
    email: { required: true, email: true, minlength: 3, remote: { url: “checkemail.php”, async: false } }
    [/code]

    If that still doesn’t work, you can do the remote validation yourself and still keep it asynchronous, you just need to provide a callback function in the remote validation check, which only submits the form if the remote validation passed:
    [code lang=”javascript”]
    $(“#subscribe_test3”).submit(function(e){
    if ($(this).valid()){
    $.get(“/check_subscribed.php”,
    { email: $(“#subscribe_test3_email”).val() },
    function(data) {
    if (data){
    $.ajax( {
    type: “POST”,
    url: “/save_subscriber.php”,
    data: “email=”+$(“#subscribe_test3_email”).val(),
    success: function(data){
    $(“#submit_result”).html(“Ajax submit results:” + data);
    }
    } );
    }
    },
    “json”
    );
    }
    return false;
    });
    [/code]

    I think the first fix should work for you, though. Let us know of the results!

  12. Thanks for greate tut!
    I’m trying use Jqurey validate for option remote following code below
    username:{
    remote: {
    url: SITE_URL + ‘/admin/user/checkUser’,
    type: ‘POST’,
    async: false,
    data: {
    username: function() {
    return $(“#username”).val();
    }
    }
    }
    }
    and this message
    messages: {
    username: { remote: “Already subscribed”}
    }
    but it doesn’t work. Please help me. I dont know how it doesnt work
    Sorry for my english.

  13. my function checkUser just echo “false”;
    But message for remote is not show. 🙁

  14. Ok, as far as I can tell that code looks ok, for it to work the following things need to be correct. You have a form with an input field with name ‘username’ which also has id of ‘username’. You have some script running at your site url which returns a string ‘true’ or ‘false’. I noticed you didn’t have a .php extension on that url, I assume there is some url rewriting going on.
    Can I ask is the form actually validating and the username showing up as invalid? Is it just the message you specified not showing up? Try adding some log statements, both in your javascript username function (use console.log() and check with firebug or chrome developer tools) and in your server side script to check that both are being called.
    Other than that I don’t think I can help without seeing the complete form html and the complete javascript validation code.
    By the way I have a code highlight plugin installed on this site. You can use it in comment posts, e.g.
    [code lang=”javascript”]
    $(document).ready(function(){
    console.log(“Document is ready”);
    });
    [/code]
    Becomes:
    [code lang=”javascript”]
    $(document).ready(function(){
    console.log(“Document is ready”);
    });
    [/code]

  15. Thank for your support.
    This is my code detail.
    HTML:
    [code lang=”javascript”]

    [/code]

    JS:
    [code lang=”javascript”]
    $(“#myform”).validate({
    rules: {
    username:{
    remote: {
    url: SITE_URL + ‘/admin/user/checkUser’,
    type: ‘POST’,
    async: false,
    data: {
    username: function() {
    return $(“#username”).val();
    }
    }
    }
    }
    },
    messages: {
    username: { remote: “Already subscribed”}
    }
    });
    [/code]

    PHP:
    i just echo “true”. That’s all!
    [code lang=”javascript”]
    function checkUser() {
    echo “true”;
    }
    [/code]

  16. The problem appears to be the PHP file, which just has a function named checkUser. Before I assumed that your remote URL was being rewritten on the server to be directed to the correct PHP code, but if this is not the case then you need to refer directly to a PHP file itself and not a function inside the php file.
    So if the php file is called checkUser.php and located inside the /admin/user/ directory your remote validation url would be SITE_URL + ‘/admin/user/checkUser.php’

    Also inside the php file you can’t just have a function, but if you do it needs to be invoked. If that is all the php file contains the function is unnecessary, but for reference if you use a function you need to invoke it.
    [code lang=”php”]
    function checkUser() {
    echo “true”;
    }
    checkUser();
    [/code]

    Hope this helps.

  17. Thanks for supporting but it’s not work T_T
    I’m using CodeIgniter Framework (www.codeigniter.com) so when i call URL following SITE_URL + ‘admin/user/checkUser’ then function checkUser will automatically invoke
    Now, i have finished that project by using another way not jquery validate, i still try to find out Jquery validate integrate with CodeIgniter.
    By the way, your blog is so cool, i have learned many thing from this site. Thanks

  18. Ah I see, I’ve never used CodeIgniter before, that function invocation sounds like fun. I’m not sure what to suggest then apart from putting log statements on the server side and using a tool like firebug or chrome developer tools to see if the remote validation request is actually taking place. You can see in the network section the requests being made and you can check the response body only contains the text ‘true’.
    Thanks for the nice comments, I’m glad the site is useful, I wish I had more time to make more posts but am really busy with work. I’ll make an extra effort to post more regularly!

  19. Hi! I have a similar solution, and when the remote validation time out or aborts, the form gets unsubmitable. Validation is still on, but the remote validation doesnt get triggered when I change the field value or submits the form again.
    Anyone experienced this problem?

    -C

  20. I’ve never experienced a problem with remote validation timing out. That’s a server side issue, but it makes sense that the validation won’t get triggered if the async attribute is set to false, since it will wait for the server to respond. With async false the validation is basically blocked until the remote validation request gets a response. You will need to sort out the reason why the request is timing out or failing, these remote validation requests should really only take a second or two to run, anything longer I think is a usability issue.

  21. This is a great example, thanks

  22. remote: jQuery.format(“{0} is already in use.”);

    I’m creating a signup form with jQuery Validate plugin, checking if username is already in use.
    Everything works, if I fill in a username that is already in the database a message like ‘xxxxxxx is already in use.’ is shown.
    However, if I fill in another username that is already in use (eg. yyyyy) the message keeps saying ‘xxxxxxx is already in use.’

  23. I have never used the jQuery.format, on the validation page it does have jQuery.validator.format, but I have never used that.

    An alternative for what you are looking for would be to use a callback function for the remote error message. So in your messages block:
    [code lang=”javascript”]messages: {
    remote: function(rule, element) {
    return $(element).val()+” is already in use”;
    }
    }[/code]

    I have not tested this at all but it should point you on the right track.

  24. it says “undefined is already in use”.

    🙁

  25. still the same problem persists.the error message does not change..

  26. I’ve done a quick test, when I submit the form I do see the updated error message with the correct text shown, however when I type text the dynamically updating error message is not displaying the input text value, but it does when the form is submitted.
    [code lang=”javascript”]jQuery(function($){
    $(“#subscribe_test4”).validate({
    rules: {
    email: {
    maxlength: 32, remote: { url: “check_subscribed.php”, async: false }
    }
    },
    messages: {
    email: { remote: function(rule, element) {
    return $(element).val()+” already subscribed”;
    }
    }
    }
    });
    });
    [/code]

  27. Can you please suggest as to how i can display the custom error message before form submission as i have a lengthy form.

  28. After some more debugging it appears that the live validation after a key press, the callback function only has one argument populated and not two, the first argument appears to be the validated text. This seems like a bug to me, but anyway, this hack should sort it:
    [code lang=”javascript”]remote: function(rule, element) {
    return (element ? $(element).val() : rule)+” already subscribed”;
    }[/code]

  29. The problem still persists. 🙁 🙁 🙁

  30. I tried all the codes posted by.

  31. I don’t think I can help without seeing your code, do you have an online version I can access, or you can email the code to chris at opencoder dot co dot uk

  32. I am using jquery Validate plugin:

    remote: function(rule, element) {
    return (element ? $(element).val() : rule)+” already subscribed”;
    }

    The code you posted, i am using the same, only thing is my request for username existing returns true or false.

    txtEmail:{required: true,email: true,
    remote: {
    url: sitename+”/user-signup”,
    type: “post”,
    data: {
    username: function()
    {
    return $(“#txtEmail”).val();
    }
    }
    }
    },

  33. I need the complete validation code, it could be some problem or conflict with another validated field. Can you send the complete validation javascript code in one block?

  34. $(“#frmSignupStep1”).validate({
    errorElement:’div’,
    errorPlacement: function(error, element) {error.appendTo (element.siblings(“.errordiv”)); },
    rules:
    {
    txtEmail:{required: true,email: true,
    remote: {
    url: sitename+”/user-signup”,
    type: “post”,
    data: {
    username: function()
    {
    return $(“#txtEmail”).val();
    }
    }
    }
    },
    txtPassword:{wanted: true, noSpace: true, rangelength: [4, 8] },
    txtConfirmPassword:{required: true, equalTo: “#txtPassword”, rangelength: [4, 8] },
    txtCompanyName:{required: true},
    txtDBAName:{ notNumber: true},
    txtWebsite: { required: true, URL: true},
    txtLastName:{required: true, alphabetsonly:true},
    txtFirstName:{required: true, alphabetsonly:true}
    },
    messages:
    {
    txtEmail: { required: “Please provide email address”, email:”Please provide valid email address”, remote: function(rule, element) {
    return (element ? $(element).val() : rule)+” already subscribed”;
    }

    },
    txtPassword: { required: “Please provide password”, rangelength:”Please provide a value between {0} and {1} characters long.” },
    txtConfirmPassword: { required: “Please confirm password”, equalTo:”The passwords provided do not match.”, rangelength:”Please provide a value between {0} and {1} characters long.” },
    txtCompanyName: { required: “Please provide company name” },
    txtLastName: { required: “Please provide last name” ,alphabetsonly: “Please provide alphabets only.”},
    txtFirstName: { required: “Please provide first name” ,alphabetsonly: “Please provide alphabets only.”}
    }
    });

  35. $(“#frmSignupStep1″).validate({
    errorElement:’div’,
    errorPlacement: function(error, element) {error.appendTo (element.siblings(“.errordiv”)); },
    rules:
    {
    txtEmail:{required: true,email: true,
    remote: {
    url: sitename+”/user-signup”,
    type: “post”,
    data: {
    username: function()
    {
    return $(“#txtEmail”).val();
    }
    }
    }
    },
    txtPassword:{wanted: true, noSpace: true, rangelength: [4, 8] },
    txtConfirmPassword:{required: true, equalTo: “#txtPassword”, rangelength: [4, 8] },
    txtCompanyName:{required: true},
    txtLastName:{required: true, alphabetsonly:true},
    txtFirstName:{required: true, alphabetsonly:true}
    },
    messages:
    {
    txtEmail: { required: “Please provide email address”, email:”Please provide valid email address”, remote: function(rule, element) {
    return (element ? $(element).val() : rule)+” already subscribed”;
    }

    },
    txtPassword: { required: “Please provide password”, rangelength:”Please provide a value between {0} and {1} characters long.” },
    txtConfirmPassword: { required: “Please confirm password”, equalTo:”The passwords provided do not match.”, rangelength:”Please provide a value between {0} and {1} characters long.” },
    txtCompanyName: { required: “Please provide company name” },
    txtLastName: { required: “Please provide last name” ,alphabetsonly: “Please provide alphabets only.”},
    txtFirstName: { required: “Please provide first name” ,alphabetsonly: “Please provide alphabets only.”}
    }
    });

  36. Ah, I think I see what the problem is, I’ve been using validation plugin version 1.7. When I tried your example it worked for me, but when I changed to use the latest version of the validation script 1.9 I am not seeing the remote error update. I think this is a bug with the plugin, it seems to have been introduced since version 1.8 onwards. Try using 1.7.

  37. Hi this is a nice tutorial! 😀 but i do have an issue with the server side part (where the remote identifies if a certain input already exists or not)..it always returns true. How can i get the value of the field to be accessed and evaluated? please help..:D below is the receiving code

    function check_if_name_exists(){
    $cname = $_REQUEST[‘cname’];

    if ($cname == “Sample”){
    echo “false”;
    }
    else {
    echo “true”;
    }
    }

  38. That looks fine server side, I think, as long as that function is triggered. How about client side, have you made sure you are getting a json result?

  39. The function is always triggered because if I assign a value to $cname = ”Sample”, the validation works fine..but if I just let $cname takes the value of $_REQUEST[‘cname’], it always returns TRUE even though I entered ‘Sample’ on the ‘cname’ field.

    Below is the code how my remote validation works:

    $(“#commentForm”).validate({
    rules: {
    cname: {
    remote: function() {
    return {
    type: “POST”,
    url: getBaseURL()+”index.php/register/register/check_if_name_exists”,
    async: false
    };
    }

    }
    },
    messages: {
    cname: { remote: “Already subscribed”}
    }
    });

  40. Hello, this is my js

    rules:{
    uname:{
    required:true,
    minlength:3,
    remote:'config.php'
    }
    },
    messages:{
    uname:{
    required:"Username field is required.",
    minlength:"Username should be atleast 6 characters long.",
    remote:"already taken"
    }
    },

  41. and this is my php code:
    [code]
    0)
    {
    echo “false”;
    }
    else
    {
    echo “true”;
    }
    ?>
    [/code]

  42. $con = mysql_connect(“localhost”,”root”,””);
    if (!$con)
    {
    die(‘Could not connect: ‘ . mysql_error());
    }
    mysql_select_db(“mass”, $con) or die(“Could not select database”);

    //if(isset($_POST[‘uname’]))
    //{
    $uname=$_POST[‘uname’];
    $query=”SELECT username FROM members WHERE username=’$uname'”;
    $result=mysql_query($query);

    if(mysql_num_rows($result)>0)
    {
    echo “false”;
    }
    else
    {
    echo “true”;
    }

  43. ya i got it now !! sorry !! i was trying with < ?php code !! remove all other comments !!

  44. According to the old documentation, the remote rule can take a String or options object. I don’t know if a function is allowed. Also one other thing to make sure is that the server side code is not returning anything else apart from the true or false string. Anything else returned is likely to evaluate to true. Going from what you are saying I don’t know what the problem is, try var dumping the _REQUEST to see what the server receives.

  45. Sorry, last comment was for Mike, Pankit, I’m not sure why that’s not working, if you want to send me a complete example I can take a look. Email chris at opencoder dot co dot uk

  46. Nice job Chris. More helpful than the jQuery Validation remote example.

  47. Hi, I try to validate and compare a formfield with a MySQL connection to check if a title is in use or not. But I can’t get it to work.

    This is my code in the check_title.php file:

    $conn = mysql_connect(“host”, “user”, “password”);
    mysql_select_db(“database”, $conn);

    title = mysql_real_escape_string($_REQUEST[“title”]);

    $query = “SELECT title FROM table WHERE title = ‘$title'”;
    $result = mysql_query(“$query”) or die (mysql_error());
    $count = mysql_num_rows($result);

    if($count) > 0) {
    echo “false”;
    } else {
    echo “true”;
    }

    If I use your code it works great.

    $title = strtolower($_REQUEST[“title”]);
    if ($title == “title”){
    echo “false”;
    } else {
    echo “true”;
    }

    This is the validation rules and message:

    $(“#validate_form”).validate({
    rules: {
    title: {
    required: true,
    remote: “includes/check_title.php”
    }
    },

    messages: {
    title: {
    required: “Title missing”,
    remote: “Title in use”
    }
    }
    });

  48. In your code your title variable is missing a $, but I assume that’s just a typo. You also have an extra bracket in your if condition, change if($count) > 0) to if($count > 0)

  49. Thank’s for fast response! Both where typos… I finally found the problem. It was a problem with the database connection. I didn’t know how to check it at first but when I realized that I can call for the check_title.php directly it was easy to solve the problem. Thank’s for a great tutorial.

  50. Thanks deue