This question builds further on the question asked here: How to map dynamic array of input fields .
I have a dynamic set of rows with each it's own input fields. These rows can be dynamically added to the DOM, so I have to use input arrays without an index ( eg fieldname[] instead of fieldname[1] etc).
The problem occurs when I use checkboxes in these rows. Since checkboxes are not submitted when they are not checked, I see no way of knowing which submitted checkbox belongs to which row values.
Example of my form:
<form>
<div class="row">
<input type="text" name="product[]">
<input type="text" name="qty[]">
<input type="checkbox" name="projectline[]">
</div>
<div class="row">
<input type="text" name="product[]">
<input type="text" name="qty[]">
<input type="checkbox" name="projectline[]">
</div>
<div class="row">
<input type="text" name="product[]">
<input type="text" name="qty[]">
<input type="checkbox" name="projectline[]">
</div>
</form>
I found an answer to a similar problem here: php array of checkboxes , but the answer obviously only applies to arrays with an index.
What is the best approach here?
EDIT :
I also check the form for errors server-side and redirect it back if it is faulty, So I need to be able to 'reconstruct' the form based on the submitted values.
I ended up assigning an index number to each of the rows, generating a new random id each time a row is added. I used jQuery for the clone functions and event binding.
Below is my complete solution.
This is my original form:
<form>
<div class="row">
<input type="text" name="product[0]">
<input type="text" name="qty[0]">
<input type="checkbox" name="projectline[0]">
</div>
</form>
I have a template row that I use to make clones of:
<div id="templaterow">
<input type="text" name="product[%%index%%]">
<input type="text" name="qty[%%index%%]">
<input type="checkbox" name="projectline[%%index%%]">
</div>
A button to clone the row:
<button id="addrow" value="add new row"/>
And a function bound to the button:
$('#addrow').on('click',function()
{
//template row is cloned and given the right attributes:
var clone = $('#templaterow').clone(true, true);
$('.row').last().after(clone);
clone.addClass('row').removeAttr('id');
// the %%index%% placeholder is replaced by a random index number between 100 and 9999999
clone.html(function (index, html) {
var rndIndex = Math.floor((Math.random() * 9999999) + 100);
return html.replace(new RegExp('%%index%%','g'),rndIndex);
});
});
One trick I've seen used for this is to put a hidden field before each checkbox that submits the same field with a value of 0. That way, if you check the checkbox it will overwrite the 0 value with the checkbox value, but if you don't, you'll get a 0 for unchecked instead of nothing in your data.
The answer from the comments of keeping a running total of indexes could work, too, but is a bit more complicated depending on how and when the DOM can be modified.