dynamic forms with jQuery
I've been using prototype for a long time. This week I decided to give jQuery a shot and realised that JS could get even funnier
As this is a nerd blog, I'm gonna try to post something useful here and teach you how to create and manipulate a dynamic forms using jQuery. There is a "special" feature when the user removes an item, the script rename the dynamic fields so the form stays sequentially ordered. Later I'm gonna show how to take advantage of this feature. But first, let me show the code:
I will assume you have already downloaded the latest version of jQuery. In my sample form I will create a hidden field called "i" with the value "1". This value indicates the ID for the next dynamic element (it may be a bit confusing right now but I guess you will get it later, please keep reading). I will also create a
to host all the dynamic elements. Now let's create a function to generate our elements:
-
function addInfo() {
-
/* I'm not using document.getElementById("something"), I'm using jQuery's $("#something") instead.
-
please check the official docs for more info... */
-
var i = $("#i").val(); // I'm gonna use an ID for each new group of elements.
-
newDiv = document.createElement('div'); // I'm also gonna create a child-div inside the "#dynamic" div.
-
newDiv.setAttribute('id', 'custom_'+i); // this new div will be named custom_1, custom_2 and so on
-
newDiv.setAttribute('style', 'display: none'); // display none? Yes, I wanna show you some effects as well.
-
newDiv.innerHTML = '<h1>Content Here!!!</h1>Custom field: <input type="text" name="custom_title_'+i+'"><a href="javascript:void(0);" onClick="javascript:delInfo('+i+');">[ Remove ]</a>'; // content... nothing special except for the "delInfo(number)" which will delete this element. I'm gonna explain this function later in this article. Oh, and the naming of our field "custom_title_"+i (remember that "i" means the element number)
-
$('#dynamic').append(newDiv); // append this as a child of "dynamic"
-
$('#custom_'+i).show("slow"); // simple effect
-
$("#i").val(++i); // Ha! Don't forget to increment your "next element" hidden field.
-
}
Once we are done adding elements we will need a way to remove them. You can do it using 1 line in jQuery. It is bloody simple, and if you are not going to use a script to handle these form fields, you don't need to care about anything else. BUT if you need to use the dynamic fields you will need to have some kind of organization. Imagine this scenario:
Your user creates two dynamic fields (custom_title_1 and custom_title_2). Then the user deletes custom_title_2 and create another field (custom_title_3). At this time, your "i" field is equal to 4 and you have 2 dynamic elements (custom_title_1 and custom_title_3). Then the form is submitted to a PHP page (lets use check.php just as an example). The logical thing to do is something like:
-
/* this is pseudo-code!! don't use it!! */
-
$i = $_POST['i'];
-
for($count = 1; $count <$i; $count ++) {
-
}
Will this approach work? probably yes, but its not optimal. You will execute this code 3 times when you have only 2 fields (ok, this example is not much convincing but try to imagine a user that removes sixty dynamic fields before submitting the form. You would have custom_title_1 and custom_title_61... this is a complete waste of resources to execute the code above. So how can we fix this? I came up with this simple delInfo() function:
-
function delInfo(custom_id) {
-
$("#custom_"+custom_id).hide("slow", function () { $("#custom_"+custom_id).remove(); }); /* deleting slowly in one line hehehe. If you want just to remove you can use only $("#custom_"+custom_id).remove(); how easier it can gets? */
-
/* div removed. now reordering to keep custom fields sequential
-
so we will not waste loops handling the dynamic form */
-
var cnt = 1; // this will store how many items I have left.
-
var limit = $("#i").val(); // this is my "next dynamic id" var.. remember?
-
for( i=1; i <limit; i++) {
-
if ($("#custom_"+i).size()> 0) { // does this element exist?
-
if (i != cnt) { /* Oops! something was deleted and this is not sequential. rename. */
-
$("#custom_"+i).attr("id", "custom_"+cnt ); // renaming the child div...
-
$('[@name=custom_title_' + i + ']').attr("name", "custom_title_"+cnt ); // ... and the field
-
}
-
cnt++; // done with this. Next please!
-
}
-
}
-
$("#i").val(cnt); // when the 'for' ends, the "cnt" var will have the real "next dynamic id" so I can replace my actual "i" value.
-
//alert($("#i").val()); // debug, activate to see how it works.
-
-
}
I'm glad you still haven't killed yourself. Now let's put everything together and see it working
This is our sample page (copy&paste, save as a regular html and don't forget to adjust the jquery.js src!!!):
-
<script type="text/javascript" src="js/jquery.js"></script>
-
<script language="JavaScript">
-
function addInfo() {
-
var i = $("#i").val();
-
newDiv = document.createElement('div');
-
newDiv.setAttribute('id', 'custom_'+i);
-
newDiv.setAttribute('style', 'display: none');
-
$('#dynamic').append(newDiv);
-
$('#custom_'+i).show("slow");
-
$("#i").val(++i);
-
}
-
-
function delInfo(custom_id) {
-
$("#custom_"+custom_id).hide("slow", function () { $("#custom_"+custom_id).remove(); });
-
/* div removed. now reordering to keep custom fields sequential
-
this is important to keep */
-
var cnt = 1;
-
var limit = $("#i").val();
-
for( i=1; i <limit; i++) {
-
if ($("#custom_"+i).size()> 0) {
-
if (i != cnt) { /* not sequential. rename. */
-
$("#custom_"+i).attr("id", "custom_"+cnt );
-
$('[@name=custom_title_' + i + ']').attr("name", "custom_title_"+cnt );
-
}
-
cnt++;
-
}
-
}
-
$("#i").val(cnt);
-
//alert($("#i").val()); // debug
-
-
}
-
-
<p>test page testing jquery to manipulate page elements</p>
-
<form name="foo">
-
<input type="hidden" name="i" id="i" value="1">
-
<!-- dynamic part. build with js -->
-
<div id="dynamic">
-
-
</div>
-
</form>
-
</body>
-
</html>
...and we didn't use any of the "hottest" things about jQuery!!
I hope you enjoyed this [not that] short post. See you next time!
-bigo
1 Comment so far
Leave a reply

Thanks, that was quite useful. There is a small problem with your script, though - in the hiding function, the callback should include all subsequent code to ensure that the renumbering doesn’t happen before the element is removed. Currently this can happen, as the remove callback might only be started after the execution of all other code.
kmh