Dynamically Adding Elements to a Form with JavaScript

Most web forms are static, as it's known in advance exactly what fields the form should show. In some cases however, you need a form that permits the user to enter a variable number of fields. Using JavaScript, you can add a button which the user can press when they need extra form fields. The button must trigger a JavaScript function to add the extra elements using the JS DOM.
compton, 30 July 08
Updated 10 September 11
In this example, we'll be looking at a form that is created within a table. The table has an id of formtable, and a few standard HTML fields. The HTML for the table is shown in the code listing below.

To test out the code, click the Activate Demo button on the top-right of the code listing. You'll then see the table and form as they'll appear to the user. Select 'Links' or 'Buttons' in the dropdown, and the textboxes will appear, along with a small button labelled with a plus sign. Press this button to add new text boxes.
<form action="/" method="post" onsubmit="alert('Form submit disabled');return false;"> <table id="formtable" border="0" cellpadding="0" cellspacing="3"> <tr> <td> Title </td> <td> Type<span style="color:red;">*</span> </td> </tr> <tr> <td> <input name="title" type="text" size="40" value="title"> </td> <td> <select name="notice_type" onchange="show_link_boxes(this.value == 1 || this.value == 3);"> <option value="">Please select..</option> <option value="1">Links</option> <option value="2">Text only</option> <option value="3">Buttons</option> </select> </td> </tr> <tr> <td colspan="2"> Notes </td> </tr> <tr> <td colspan="2"> <textarea name="description" rows="3" cols="40">description</textarea> </td> </tr> <tr id="opt0" style="display:none"> <td> Label<span style="color:red;">*</span> </td> <td> Link<span style="color:red;">*</span> </td> </tr> <tr id="opt1" style="display:none"> <td> <input type="text" name="opt_title[]" maxlength="255" size="40"> </td> <td> <input type="text" name="opt_url[]" maxlength="255" size="40"> </td> </tr> <tr id="opt_controls" style="display:none"> <td align="right" colspan="2"> <input type="button" onclick="add_opt_row()" value="+"> </td> </tr> <tr> <td align="right" colspan="2"> <input type="submit" value="Submit"> </td> </tr> </table> </form>
Title Type*
Notes

The JavaScript Functions

Let's now have a look at the two JavaScript functions that provide this functionality. The first one, show_link_boxes(), simply shows or hides the textboxes as well as the button for adding new textboxes. As you can see if you study the HTML code listing above, this function is called by the onchange attribute of the dropdown list, such that the textboxes appear when the drop-down is set to either 'Links' or 'Buttons' and are hidden otherwise.
<script language="javascript"> function show_link_boxes(visible) { // Iterate through all rows of the table var rows = document.getElementById('formtable').getElementsByTagName('tr'); var total_rows = rows.length; for (var index = 0; index < total_rows; index++) { // Set display property of all rows with an id beginning with 'opt' if (rows[index].id.substr(0, 3) == 'opt') { rows[index].style.display = visible? '' : 'none'; } } } </script>

Adding Textboxes to the Form

The other function, add_opt_row(), is more interesting to us. It adds a new table row, comprising two table cells each containing a new text box. It begins by iterating through all table rows of our table. Note how getElementsByTagName() is again used to select only those rows that belong to the table with an id of formtable.

When we create the two new textboxes with document.createElement('input'), we set the name attribute to opt_title[] and opt_url[] respectively. Using names with a pair of empty square brackets like this means that in PHP, we can access all POST values that have this name as a single array, eg $_POST['opt_title'][0], and therefore we can iterate through all such values using foreach, thus allowing us to easily access however many fields the user chose to add.

We also set a few other attributes for the textboxes before each one is added to a separate table cell. The two table cells are then added to a new table row which is in turn added to the table using the insertBefore() function on the last line of this function. At this point, the two new textboxes appear and are ready for the user to enter values.
<script language="javascript"> function add_opt_row() { var rows = document.getElementById('formtable').getElementsByTagName('tr'); var highest_id = 0; var total_rows = rows.length; for (var index = 0; index < total_rows; index++) { if (rows[index].id.substr(0, 3) == 'opt' && !isNaN(rows[index].id.substr(3))) { if (Number(rows[index].id.substr(3)) > highest_id) highest_id = Number(rows[index].id.substr(3)); } }   // Create 2 new table cells var cell1 = document.createElement('td'); var cell2 = document.createElement('td');   // Create a new input textbox in each var inputbox = document.createElement('input'); inputbox.type = 'text'; inputbox.name = 'opt_title[]'; inputbox.maxLength = 255; inputbox.size = 40; cell1.appendChild(inputbox);   inputbox = document.createElement('input'); inputbox.type = 'text'; inputbox.name = 'opt_url[]'; inputbox.maxLength = 255; inputbox.size = 40; cell2.appendChild(inputbox);   // Create new row & add tds to row var newrow = document.createElement('tr'); newrow.id = 'opt' + (highest_id+1); newrow.appendChild(cell1); newrow.appendChild(cell2);   // Add rows to appropriate place document.getElementById('opt_controls').parentNode.insertBefore(newrow, document.getElementById('opt_controls')); } </script>