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:
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?
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.
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!