A reader on another post asked me about using jQuery to dynamically add form fields to an existing form. I whipped up a quick demo that I'd like to get folks opinions on. Here is what I came up with:

<cfif not structIsEmpty(form)> <cfdump var="#form#"> </cfif>

<html>

<head> <script src="/jquery/jquery.js"></script> <script> var current = 1;

function addPerson() { console.log('running addPerson') //current keeps track of how many people we have. current++; var strToAdd = '<p><label for="firstname"'+current+'">Name</label> <em></em><input id="firstname'+current+'" name="firstname'+current+'" size="25" /> <input id="lastname'+current+'" name="lastname'+current+'" size="25" />' strToAdd += '<p><label for="email'+current+'">Email</label> <em></em><input id="email'+current+'" name="email'+current+'" size="25" /></p>' console.log(strToAdd) $('#mainField').append(strToAdd) }

$(document).ready(function(){ $('#addPerson').click(addPerson) }); </script> </head>

<body>

<form id="someform" method="post"> <fieldset id="mainField"> <p> <label for="firstname1">Name</label> <em></em><input id="firstname1" name="firstname1" size="25" /> <input id="lastname1" name="lastname1" size="25" /> </p> <p> <label for="email1">Email</label> <em></em><input id="email1" name="email1" size="25" /> </p> </fieldset>

<p> <input type="button" id="addPerson" value="Add Another Person"> </p>

<input type="submit" value="Save"> </form>

</body> </html>

I want to talk about this from the bottom up, so please read 'up' with me. The form contains one block of detail for a person - a firstname, lastname, and email address. There are two buttons - one to add another person and one to submit. This is what I started off with as the base form. I wanted it so that when you clicked Add Another Person, it would essentially duplicate the 3 fields.

I began by telling jQuery to monitor the click event for the button (inobtrusive JS FTW):

$(document).ready(function(){ $('#addPerson').click(addPerson) });

addPerson then had to do two things. First, it needed to know how many people existed on the page already. I had created a JavaScript variable, 'current', with a hard coded value of 1. This doesn't need to be hard coded, but it certainly seemed to be the simplest way to handle it. Inside of addPerson, I immediately increase the value by one. I generate the HTML I want to use which was basically a cut and paste of the HTML below. The only difference is that I make the number part dynamic. I could have probably used a special character like $N and then used Regex to replace it. (On second though, that would have been a lot cleaner I think.) Then I just append the new string to the HTML.

You can view this here.

So a few open questions/things to discuss:

  1. jQuery provides a clone() function for the DOM. In theory, I could have just cloned my fieldset. The problem with that (as far as I know) is that I'd end up with form fields that have the same name. That "works" in CF, but the values would be a list. So for example, form.firstname would be "Ray,Jay". That works well until someone has a comma in their name. Not very likely, but still. I believe in PHP it actually gives you the values in an array, but in CF we have no control over that. Maybe I could have done a clone, gotten the new node, and did the regex on the HTML?

  2. I didn't demonstrate the CF side to parse this because I've done so many times before, but in case folks are curious - you would simply introspect the Form struct to figure out how many people you have to process.

  3. Of course, the next step is to add validation. I'm willing to bet I can use the kick butt jQuery Validation plugin with dynamic forms. I'll check that next!