HTML Forms With Dynamic Input Groups

Today I was working on a project that has a form where at the beginning, there is an unknown number of field groups, and the field groups have to be tied to each other. The resulting data object needs to look like this:

{
"series": "Superstore",
"characters": [
{
"characterName": "Amy",
"actorName": "America Ferrera"
},
{
"characterName": "Jonah",
"actorName": "Ben Feldman"
},
{
"characterName": "Glenn",
"actorName": "Mark McKinney"
}
],
},

Sure I could have a form with a loooooot of input fields, but that would look bad, would be inefficient, and would result in empty results I’d need to filter out.

Thanks goodness for the article I found, A little trick for grouping fields in an HTML form, which spells out very clearly how you can use brackets [] in HTML form names to structure the resulting form body data. In this case:

<div class="two fields">
<div class="field">
<label for="characters[character0]characterName">Character Name</label>
<input type="text" name="characters[character0][characterName]" id="characters[character0][characterName]" laceholder="Character Name">
</div>
<div class="field">
<label for="characters[character0]actorName">Actor Name</label>
<input type="text" name="characters[character0][actorName]" id="characters[character0][actorName]" placeholder="Actor Name">
</div>
</div>

Even more handy, the article also gave some tips on how to make the form dynamic, so that you can add additional field groups if you need more, which I implemented:

<script>
let i = 1;

document.getElementById('add-new-person').onclick = function () {
let template = `
<div class="two fields">
<div class="field">
<label for="characters[character${i}]characterName">Character Name</label>
<input type="text" name="characters[character${i}][characterName]" id="characters[character${i}][characterName]" placeholder="Character Name">
</div>
<div class="field">
<label for="characters[character${i}]actorName">Actor Name</label>
<input type="text" name="characters[character${i}][actorName]" id="characters[character${i}][actorName]" placeholder="Actor Name">
</div>
</div>
`;

let container = document.getElementById('character-container');
let div = document.createElement('div');
div.innerHTML = template;
container.appendChild(div);

i++;
}
</script>

I also found a very easy way to get the whole array in one go, without needing any loops or map, etc. by using the Object.values() method. As a result I can create the model from the form data to enter into the database as simple as:

let newSeries = {
name: req.body.seriesTitle,
characters: Object.values(req.body.characters),
};

All of these are good reference for future!