enpaul enpaul - 4 months ago 14
Javascript Question

JS form validation for dynamically built form in a table

EDIT: I am using Foundation 6 with the Abide Form Validation.

I'm trying to do automatic form validation for a website. What I've done is create a table (using the jQuery Datatables library) with a series of inputs in the first row. Then the user uses an 'add new row' button to add more rows (with identical input fields, but unique names/ids) as needed.

Everything is working fine so far, except now when I am attempting to validate the inputs, only the first row is being checked. I'm new to JS and jQuery, so I'm picking up a lot of this stuff as I go, but I think what I'm trying to do is refresh the table's DOM element so that the newly added inputs are included in validation. I just can't seem to figure out how to get the DOM to refresh.

The actual table and scripts are complicated, so in the interest of simplicity the code below is a simplified version of what I'm working with:

HTML:

<form data-abide novalidate action="processRequest.php" method="post" name="processRequest">
<button class="button">Submit Request</button>
<table id="Request" class="display">
<thead>
<tr>
<th>Type*</th>
<th>Product*</th>
<th>Command*</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select name="RequestType0" id="RequestType0" required>
<option></option>
<option>New</option>
<option>Resize</option>
<option>Restyle</option>
</select>
</td>
<td>
<select name="RequestProduct0" id="RequestProduct0" required>
<option></option>
<option>Product1</option>
<option>Product4</option>
<option>Product3</option>
</select>
</td>
<td>
<input type="text" name="RequestCommand0" id="RequestCommand0" placeholder="Command" required/>
</td>
</tr>
</tbody>
</table>
<!-- Add new row -->
<button class="button" id="add_row" type="button"><i class="fa fa-lg fa-plus" aria-hidden="true"></i></button>
</form>


jQuery Datatables Construction Script:

$(document).ready(function() {
var table = $('#Request').DataTable( {
"ordering": false, // Globally disables reordering of the table on all columns
"bLengthChange": false, // Disable user ability to change # of results shown
"searching": false, // Disable user search filtering field
"info": false, // Disable info box
"processing": false, // Disable showing the 'processing' indicator on refresh
"paging": false, // Disables paging
} );
} );


Add New Row Script:

$('#add_row').on("click", function newRow() {
var table = $('#Request').DataTable().rows();
var len = table.rows().count();

var cell0 = table.cell(len-1,0).node();
var cell1 = table.cell(len-1,1).node();
var cell2 = table.cell(len-1,2).node();

table.row.add( [cell0.innerHTML, cell1.innerHTML, cell2.innerHTML] ).draw(true);

table.cell(len,0).node().childNodes[1].setAttribute('name', 'RequestType' + len);
table.cell(len,0).node().childNodes[1].setAttribute('id', 'RequestType' + len);
table.cell(len,1).node().childNodes[1].setAttribute('name', 'RequestProduct' + len);
table.cell(len,1).node().childNodes[1].setAttribute('id', 'RequestProduct' + len);
table.cell(len,2).node().childNodes[1].setAttribute('name', 'RequestCommand' + len);
table.cell(len,2).node().childNodes[1].setAttribute('id', 'RequestCommand' + len);
});

Answer

From the data-abide attribute, I assume you are using Abide Validation:

Adding New Abide Content After Page Load

If you add new content after the page has been loaded, you will need to reinitialize the Foundation JavaScript by running the following:

$(document).foundation('abide', 'reflow');

Reflow will make Foundation check the DOM for any elements and re-apply any listeners to them.

You need to run this code each time a row is added.