Kalabasa / htmz

html with targeted manipulation zones

Home Page:http://leanrada.com/htmz/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

Screenshot 2024-02-24 at 10 53 55

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.