html icon indicating copy to clipboard operation
html copied to clipboard

Add form persistence

Open FrameMuse opened this issue 5 months ago • 7 comments

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.

FrameMuse avatar Jun 01 '25 12:06 FrameMuse

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 localStorage or sessionStorage, 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 formStateRestoreCallback Custom 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.

keithamus avatar Jun 16 '25 14:06 keithamus

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 id or name field is a requirement, I just wasn't sure which one would fit better, if you say id I'm fine. I also put name since that's how forms are indexed in document.forms>.

FrameMuse avatar Jun 17 '25 12:06 FrameMuse

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).

FrameMuse avatar Jun 17 '25 12:06 FrameMuse

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.

FrameMuse avatar Jun 17 '25 12:06 FrameMuse

There already exists the formStateRestoreCallback Custom Element Reaction <...>

  • I haven't seen that, will look into it.

perhaps a restore event 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.

formStateRestoreCallback

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 formStateRestoreCallback is 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?

FrameMuse avatar Jun 17 '25 12:06 FrameMuse

(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.)

domenic avatar Jun 18 '25 01:06 domenic

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 formStateRestoreCallback Custom 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 persist or such attribute/property is present on form element. Form data restoration should happen only if developer meant this behavior beforehand.

FrameMuse avatar Jun 18 '25 12:06 FrameMuse