Too Complex for a Form
I often use - and, sometime, abuse - dynamic tables as a design pattern: an HTML table with a button to add new rows, each row contains multiple inputs to define details of an entity, the whole set is submitted once on the server for persistency. I adopt this so often that I've implemented it on my own jQuery utilities library, and I include this kind of element in almost all applications I implement.
It is easy as long as each input includes a single value, and their name
attribute can be wrote in array-like syntax to enforce submit of all the values to be then iterated server-side: all inputs at index 0 refers to the first row, all inputs at index 1 refers to the second row, and so on. The difficult part is when multiple values are involved in a single input, such as in checkboxes or tags, as you loose the same-index map or related values and you are no longer able to rebuild the correct structure.
So, I've been a bit radical on my latest implementation. On form's submit, using dynamicFunctions
feature from the same jBob library above mentioned, I just serialize the table in a JSON array which is then serialized and appended to the form. In this way, the hierarchy can be of any complexity: each row in the table is converted in a self-contained JSON object, isolated from the others, which can be easily handled on the server.
In JS:
var j = new jBob();
j.init({
dynamicFunctions: {
jsonableTable: (form) => {
let complete = [];
form.find('tbody').find('tr').each((index, node) => {
let row = $(node).find('input, select, textarea').serializeArray();
if (row.length == 0) {
return;
}
let obj = {};
row.forEach((r) => {
let name = r.name.replace(/\[.*\]/g, '');
if (obj.hasOwnProperty(name)) {
if (Array.isArray(obj[name])) {
obj[name].push(r.value);
}
else {
let arr = [];
arr.push(obj[name]);
arr.push(r.value);
obj[name] = arr;
}
}
else {
obj[name] = r.value;
}
});
complete.push(obj);
});
let json = JSON.stringify(complete);
let appended = form.find('input[name=jsonable]');
if (appended.length == 0) {
appended = $('<input type="hidden" name="jsonable">');
form.append(appended);
}
appended.val(json);
},
}
});
In HTML:
<form class="dynamic-form">
<input type="hidden" name="jb-pre-saved-function" value="jsonableTable">
<table class="dynamic-table">
<tbody>
<tr>
<td><!-- Your inputs with multiple values --></td>
</tr>
</tbody>
<tfoot hidden>
<tr>
<td><!-- --></td>
</tr>
</tfoot>
</table>
</form>
Naive, but practical.