html
html copied to clipboard
Add form persistence
What problem are you trying to solve?
As you may know forms are very common UI widget and it's also common for user to have a stroke whenever it fills in inputs just to find out that it's all gone after accidental navigation or modal closure. It would be nice if browsers have a way to tell a form to restore data for its inputs and save sanity for many users.
What solutions exist today?
It could be done by JS, but with a browser implemented way it could be just a breeze for developers to introduce their persistence per form and it doesn't require creating "special" elements or scripts for each input to save data somewhere. It also can store more data than regular localStorage or sessionStorage as it'd be closed Browser API and it seems to be safe since AFAIK all input values are always strings.
How would you solve it?
I propose to add a property to form element to command it to restore its FormData to whatever it was.
Data could be either saved to local storage (for a domain) or session one (for a browser tab) by choosing between persist="local" and persist="session".
For it to work, a form must have either id or name and it will save/restore only those inputs, which also have it.
Each input could also define if it's restorable or not.
<form id="myform" name="myform" persist="local" persist="session">
<input name="1" />
<input name="2" />
<input name="3" />
</form>
Anything else?
Thanks for your feedback.
Discussed this with fellow Mozillians and we have some comments:
- It may be tricky to correctly serialize the data coming out of a form especially as the form changes between sessions, for example generated names would make this trickier, as well as lack of field names or a form ID. So we agree, it would likely be a requirement that only forms with IDs can be persisted.
- It might not be ideal to put this behind an API like
localStorageorsessionStorage, instead we might opt to use a storage mechanism which is not web exposed due to various constraints: likely we don't want developers to modify the data, the storage may not always be guaranteed, etc. - Browsers already have this concept, especially on mobile - where processes may shutdown and restore more aggressively. It might be worth trying to leverage or standardise the same mechanisms here, but this might limit the available scope of what we can expose.
- There already exists the
formStateRestoreCallbackCustom Element Reaction, which is used when UAs attempt to restore or autofill a Form Associated Custom Element's field. Perhaps we can apply a similar level of abstraction for this case: perhaps arestoreevent on forms could be emitted by UAs at their own discretion, and web developers can use scripting to listen for the event and fill the relevant fields (which also allows developers to handle issues around migration/validation and so-on). This would allow developers to opt in via the event, rather than an attribute on the form.
Sorry I guess I didn't make it clear enough, but many things you mentioned was something I already stated.
Then let me clarify
So we agree, it would likely be a requirement that only forms with IDs can be persisted.
- Yes, the
idornamefield is a requirement, I just wasn't sure which one would fit better, if you sayidI'm fine. I also putnamesince that's how forms are indexed indocument.forms>.
It might not be ideal to put this behind an API like localStorage or sessionStorage, instead we might opt to use a storage mechanism which is not web exposed <...>
Yes, that's what I meant, I made the options local and session exceptionally for similarly to localStorage and sessionStorage. I also mentioned that form persistence should happen out of browser exposed API to be more secure and avoid aggressive storage cap.
I think this also goes with namedItem well since it uses either id or name (source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection/namedItem).
Browsers already have this concept, especially on mobile - where processes may shutdown and restore more aggressively. It might be worth trying to leverage or standardise the same mechanisms here, but this might limit the available scope of what we can expose.
- Yes, when you fill in form fields and accidentally close the window and then reopen, the data is restored. The problem is that it won't work for programmatically created inputs i.e. for every SPA app, which is very unfortunate.
There already exists the
formStateRestoreCallbackCustom Element Reaction <...>
- I haven't seen that, will look into it.
perhaps a
restoreevent on forms could be emitted by UAs <...> This would allow developers to opt in via the event, rather than an attribute on the form.
Maybe. My intention of an attribute for form was so that you can have persistence without scripting, making it declarative. If this is not possible we can discuss other approaches to it, I'm open to everything, though my lovely variant would be a defined property, attribute, callable method for form restoration or API for form cache, accessible at will in browsers like
const form = document.forms.myForm
form.persist = "local" // Not at `localStorage`, but between tabs for the same domain.
form.restore() // Data can be restored unless any input was made after form appeared or form submit/reset.
As per this link (at the moment I write this):
When user agent updates a form-associated custom element's value on behalf of a user or as part of navigation, its
formStateRestoreCallbackis called, given the new state and a string indicating a reason, "autocomplete" or "restore", as arguments.
This is related to the custom HTMLFormElement behavior and navigation, which is ok, however my proposal is to add a feature of persisting named inputs of named forms with least effort possible.
The persistence of forms already can be well done with scripts and localStorage. The proposal is to avoid scripting at all, so that pages that do not use JavaScript can also use form persistence.
You can imagine a website that handles form with PHP, so if form submitting, auto-filling, validating can be done without scripts, why it can't be persisted?
(In the future, please consider responding once, instead of four times, as each response sends an email to 700+ people. If this means waiting until you're at a computer, so you can give a more thoughtful response, that's even better. There is no need to respond to this message.)
Thanks @domenic, you gave me a fresh look at my proposal again.
Forms persistence may be User engaged instead of fully "automatic":
Named forms with named inputs (and with persist/restorable attribute) can be restored from User acceptance (not sure what UI should look like).
If a named form has persist attribute and User accidentally closes, for example, dynamically created popup with the form, which filling in took an hour. And then User opens the popup again with shaking hands, the browser would give a hint that User can restore his precious data. I imagine it as auto-filling when I choose my login from the list, which would also fill other fields (like email, password).
This behavior can be customized by listening to a form event (e.g. restore) and if event.preventDefault is called, user will be hinted nothing. This means custom hinting UI can be implemented by a developer and then if user clicks restore button in custom UI, form.restore can be called to confirm restoration.
Of course, another mechanism can be implemented, here's an alternative (I'm just brainstorming):
restore event would contain FormRestorationRequest e.g. in event.restorationRequest, which could be stored somewhere. It would be alive until form is submitted, reset or stale (let it be 1 week).
The interface may look like this
interface FormRestorationRequest extends AbortController {
restore(): void // Restores form data.
readonly lastEdited: number // Timestamp when the last edit to form inputs was made.
}
Edge case: User may introduce updates just after restore event fired, then FormRestorationRequest can be immediately aborted OR a little action window can be given until aborting the request, so that user could fill in some fields and restore other ones (though not sure if this useful).
This is based on this idea:
There already exists the
formStateRestoreCallbackCustom Element Reaction, which is used when UAs attempt to restore or autofill a Form Associated Custom Element's field. Perhaps we can apply a similar level of abstraction for this case: perhaps a restore event on forms could be emitted by UAs at their own discretion, and web developers can use scripting to listen for the event and fill the relevant fields (which also allows developers to handle issues around migration/validation and so-on). This would allow developers to opt in via the event, rather than an attribute on the form.
Stepping from form events, form object can have an array of its unsubmitted versions.
If any present, a developer can implement custom UI for User-engaged OR script-based form data restoration. Not sure about many versions, one should go also (I'm just overthinking).
[!NOTE] That this all happens only if
persistor such attribute/property is present onformelement. Form data restoration should happen only if developer meant this behavior beforehand.