Let's say I have a form where I need to enter a list of items (names, in our case). The form should allow the user to input any number of items, and each item should be editable, either by literally changing the item or just deleting it altogether.
How would I create this using standard web technologies? I've made two rough attempts at it below ("rough" being the key word; I made these examples very quickly, and I'm still a novice at both forms and accessibility on the web).
Single enabled input
For this method, I use a single text input at the top of the list, with the items themselves being read-only.
Make a reservation
FormData = {}
Some things to note about this approach:
-
The main input to add items to the list is not submitted with the form, so it isn't given a
nameattribute. - The added names are displayed using readonly inputs, which is how they end up in the form's submitted data.
- Since editing entries is not possible, the best alternative is to delete and re-enter.
This approach seems to work well when the data is simple, and the delete/re-enter workflow isn't too cumbersome.
List of editable inputs
For this method, each entry in the list is an editable input.
Make a reservation
FormData = {}
Some things to note about this approach:
- The visual styling of the list is finicky. To prevent the list from appearing cluttered, the inputs have to appear both subtle while also appearing editable.
- Validation is also finicky, but there are a number of different approaches you could take. I've chosen to prevent the user from submitting empty values, and only alerting empty values on submit.
This approach requires a lot more work to implement and get right. I don't think it's particularly worth it when the data is simple. But if, for example, the list asks for a name, email, and phone number for every entry, it would be nice to have editable rows like this. In that case, it might also be worth it to enable editing per row using an edit button.
Combining the two approaches
In theory, you could combine these two approaches: have a single text input to initialize each value, then allow inline editing of each item.
In practice, this approach introduces ambiguity to the user experience without careful consideration. The interface must somehow make clear that the input to add a new item is not itself an item, and it will not be submitted with the form.
Consider a textarea
For a list of names, why not just have the user enter everything in a single textarea with names delimited by commas or newlines? When the data is simple, this option coudl be worth considering.
If each list entry is more complex than just a name, however, a textarea alone won't provide enough structure to guide the user to a valid input.
Bonus: progressive enhancement
I'm using custom elements to add DOM manipulation to the above examples to make this work. It's important to remember that these patterns require JavaScript to function like they do.
It's worth asking: how would a progressively-enhanced version of either approach function without JavaScript?
The simplest version probably looks more like the multi-input example. The page gives a base number of inputs to work with. The user then has two options: they can submit the form as complete, or they can request more inputs from the server.
Make a reservation
FormData = {}
An even more sophisticated version might allow you to submit a partial form response specifying the desired number of items in the list, and the server would respond with an updated page with the corresponding inputs. Honestly, once you get a server involved, the no-JavaScript version of the form can be as sophisticated as you want.
Other challenges and closing thoughts
One problem I haven't tackled in these examples is how to label the inputs for the list items. I'm sure I should use some combination of fieldset and hidden labels, but the content of the labels eludes me.
I also didn't tackle proper focus management for keyboard users. If focus is on the "Add" button in each example, and you've added ten entries, you have to tab through each entry and its delete button to reach the submit button. I think it would be better to tab to the entire list, then give finer control using the arrow keys.
Finally, there are just lots of choices to make when it comes to styling and placement of elements:
- Should the "Add" button go before or after the list?
- Should the button to delete an individual entry go before or after the entry? Should there be a different delete mechanism?
- How should individual list entries be styled?
- What validations are appropriate, and when should they be applied?
The correct approach to any of these problems is dependent on context. I have a specific use case in mind for these experiments, but a different set of requirements could change everything about the styling, layout, and validation.
Final thought from a form novice: forms are really powerful!