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!