Twitter: raymondcamden


Address: Lafayette, LA, USA

Using jQuery to add form fields - with validation

02-22-2009 23,976 views jQuery 10 Comments

A few days back I posted a blog entry on using jQuery to dynamically add form fields to a form. The example I gave was a form that asked you to enter information about a person and then had a simple way to add new people to the form. I asked for - and got - a lot of feedback on other (better!) ways to write the code. I've taken one of the suggestions from Brian Swartzfager (see his demo here) and used it for my next task - adding validation to the form, including validation on the new fields. Definitely view source on his demo as I'll be assuming you have read it.

Alright - so the first thing I wanted to do was add validation to the form fields that showed up by default. I am a big believer in 'baby steps' so before I even try to make the validation dynamic, I'll work with the static form fields first. Brian's code already had a (document).ready block, so I simply added the following:

view plain print about
1$("#demoForm").validate({
2
3    rules: {
4        firstname1: {
5            required: true,
6            minlength: 2
7        }
8        ,lastname1: {
9            required: true,
10            minlength: 2
11        }
12        ,email1: {
13            required: true,
14            email: true
15        }
16    }

If you have read my entries on form validation with jQuery than the above shouldn't be anything new. I verified this worked before going on.

It is a bit off topic for this entry, but notice how my form uses one label for first and last name? Notice how since both are required, if you forget both, the error message displays by each field? It would be nice if there was a way to say "Yes, firstname and lastname are required, but I want to treat them as a group and just one error message." Turns out - the plugin supports this out of the box. You can create a group of form fields using the groups value in the constructor. This will group the fields in terms of messaging. We still need a way to specify where the error should go. This can be done with yet another constructor value - errorPlacement. Consider:

view plain print about
1groups: {
2    fullname: "firstname1 lastname1"
3},
4errorPlacement: function(error, element) {
5    if (element.attr("name") == "firstname1" || element.attr("name") == "lastname1" )    
6        error.insertAfter("#lastname1");
7    else
8        error.insertAfter(element);
9},

I've created an arbitrary group name called fullname and linked it to my two name fields. The errorPlacement value is a function that can dynamically handle putting the message in the right place for my name 'set'. FYI, I think this is a bit overly complex. I can see needing custom error placement about 100% of the time for groups. I've filed an enhancement request for the plugin to make this a bit easier.

Okay - sorry for the diversion there. So given that we can now validate the form fields built in, and we have an easy way to add more fields, how do we also add validation for the new rules? The Validation plugin makes this simple. For each new field we add, we can do: X.rules("add", rule) where X is our selector the rule is the logic to add. Taking Brian's code he wrote for the addPerson logic, I just added:

view plain print about
1//add validation
2$("#firstname"+current).rules("add", { required:true,minlength:2 });
3$("#lastname"+current).rules("add", { required:true,minlength:2 });
4$("#email"+current).rules("add", { required:true,email:true });

Remember that current was a number that kept track of how many people we had in the form.

You can see this in action here: http://www.coldfusionjedi.com/demos/jqueryvalidation/testadd.cfm View source to see the complete modification to Brian's code.

This leaves us with one small little issue. While grouping nicely handles our default firstname/lastname pair, you can't add new groups after the form has been validated. (You know, I wonder what happens if you just run validate() again?) So the error display isn't terribly nice, but that could probably be worked on a bit more.

Anyway - I hope this is helpful to folks.

Related Blog Entries

10 Comments

  • Commented on 02-24-2009 at 9:09 AM
    In the interest of encapsulation and DRY, I'd consider putting validation into its own function that can be called in the $(document).ready() function and also within the addPerson click function. It may have to be made a bit more dynamic to handle this, but as the form grows, it would be easier to maintain.

    Also along the lines of DRY, in the initial html I would suggest not hardcoding the firstname1, etc. block in the html. Take the meat of that $("#addPerson").click function and put it into a separate function. Set var current = 0. Then document.ready could call that function to clone the first set of inputs.

    One more note concerning submitting empty hidden fields (the template fields). Josh N commented in the original blog post about putting that userTemplate div outside of the form itself so they don't get submitted. Seems like a good way to go to me.
  • Commented on 09-17-2009 at 9:04 PM
    Hey Raymond,

    Thanks a lot for this post. Your discussion on groups and errorPlacement helped me A TON!
  • Commented on 10-18-2009 at 4:00 PM
    Ray, this is a great example. Easy to follow and use.

    So, one last item. How do you delete the last 'add' in case the user click on 'Add Another Person' one time too many?
  • Commented on 10-18-2009 at 5:55 PM
    Better yet, how would you delete any added set?
  • Commented on 10-18-2009 at 10:19 PM
    You can, I believe, just use the remove() operator in jQuery.
  • Commented on 10-20-2009 at 10:58 AM
    Thanks Ray,

    I have it working. I will make the changes to your code and send it up to you.
  • Commented on 10-20-2009 at 12:01 PM
    I have modified Ray's code to add a 'remove' link for each new added person.

    You may find the code at : http://pastebin.com/f76dd446b
  • JFJ #
    Commented on 03-11-2010 at 12:48 PM
    Gary your changes break the validation.
  • Chap #
    Commented on 10-20-2010 at 3:39 PM
    @jfj: what browser did you see the break in? I'm not seeing anything broken.
  • Carlos #
    Commented on 01-12-2012 at 1:51 PM
    Thanks!! I was looking for this and landed right in the good spot! :)

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty