Forms with list inputs & required
angusjf opened this issue · comments
Hey Lean, firstly let me say fantastic project and such an inspiring use of the web. I can feel the future of web development starting to take shape!
Lots of tools I write are basically just forms. However, we can't write them with "just HTML" because we often need to input a list of elements, for example data like this:
{
"firstName": "Angus",
"hobbies": [ "cooking", "running" ]
}
And a form that could submit this could look like this:
<form method='post' action='/submit'>
<input name='firstName' value='Angus' required>
<input name='hobbies[]' value='cooking'>
<input name='hobbies[]' value='running'>
<button id='add-hobby' formaction='/add-hobby'>add hobby</button>
<input type='submit'>
</form>
This nearly works, but sadly not quite as the form must be valid before you can submit it.
Can you think of a workaround for this? All I can think is:
- Nested forms (disallowed)
- Using a link instead of a button (can't be clicked twice in a row)
- Just do all validation on the backend, and return a half-completed form in the case of errors (might actually be ok?)
I wonder if anyone has any ideas? Small forms like this are so close to being HTML only, but this list-of-inputs thing stops me every time - meaning I have to duplicate rendering code on the client (then I might as well just write everything client side).
HTML was so close with the multiple
attribute, but it only works for emails & files. Some kind of pill / tag input UI library is probably your best bet for a smooth user experience.
But if are OK with a roundtrip to the server on every hobby:
<!-- html form -->
<form ...>
...
<div id='hobby-list-end'></div>
<button formaction='new-hobby.html#hobby-list-end' formtarget=htmz>Add hobby</button>
...
</form>
// new-hobby.html
<input name='hobbies[]' placeholder='new hobby'>
<div id='hobby-list'end></div>
Not sure if that works, but that's the idea. You can also check the todo example.
@Kalabasa Thanks for the reply. The problem is that clicking the button (which submits the entire form to new-hobby.html#hobby-list-end
is disallowed by the validation on the other (unrelated) form elements. The form serves a dual purpose (submitting all the data & getting new HTMZ inputs) but the browser doesn't understand this.
To be fair, maybe it's a bad solution to the problem anyway. As you say, going to the server for every hobby is not ideal, and there are a few low-JS solutions that don't require this.
(for example you could use a <template>
)
<form method="post" action="/submit">
<label>
First name
<input name="firstName" required />
</label>
<fieldset>
<legend>hobbies</legend>
<template id="new-hobby">
<div>
<input name="hobbies[]" required />
<button type="button" onclick="this.parentElement.remove()">×</button>
</div>
</template>
<button type="button" onclick="this.before(document.getElementById('new-hobby').content.cloneNode(true))">
add hobby
</button>
</fieldset>
<input type="submit" />
</form>
I see! because of the required attribute. Anyway, your JS solution is pretty good and self-contained! Nice work. After seeing this, I couldn't think of any other better way.