
form-saver is a Web Component that saves unfinished HTML form values to localStorage and restores them after a page reload.
It works with existing form markup and can retain selected fields after submission.
Features
- Automatically saves changes from
inputandchangeevents. - Restores text fields, textareas, checkboxes, radio buttons, and single- or multiple-select controls.
- Adds an optional checkbox for retaining selected fields after submission.
- Supports custom storage keys for forms that share an action URL.
- Reports storage failures through a custom event.
How To Use It
1. Load the component
Form values are stored as readable JSON in localStorage, where scripts on the same origin can access them.
Load the component’s registration script:
<script type="module" src="https://cdn.jsdelivr.net/npm/@aarongustafson/[email protected]/define.js"></script>
2. Wrap your form
Add <form-saver> around the form. It saves values from the first descendant <form>. Each field needs a name or id to be restored.
<form-saver>
<form action="/contact" method="post">
<label>Name <input name="name" autocomplete="name"></label>
<label>Email <input name="email" type="email" autocomplete="email"></label>
<label>Message <textarea name="message"></textarea></label>
<button type="submit">Send</button>
</form>
</form-saver>
3. Use npm in a JavaScript project
Install the package and import its registration entry in your app:
npm install @aarongustafson/form-saver
import '@aarongustafson/form-saver/define.js';
For manual registration, import the class from the package root:
import { FormSaverElement } from '@aarongustafson/form-saver';
customElements.define('form-saver', FormSaverElement);
4. Keep contact details after submission
Set retain to the fields you want to keep after a native form submission navigates away. Add retain-choice to let visitors opt in. Leaving it unchecked clears all saved data on navigation.
<form-saver
retain="name email"
retain-choice
retain-choice-label="Remember my contact details"
retain-choice-container=".save-preference"
>
<form action="/contact" method="post">
<label>Name <input name="name"></label>
<label>Email <input name="email" type="email"></label>
<label>Message <textarea name="message"></textarea></label>
<div class="save-preference"></div>
<button type="submit">Send</button>
</form>
</form-saver>
5. Clear a draft after an AJAX submission
Native submissions clear or filter the saved draft on pagehide after the submit event, regardless of the server response. For fetch() submissions, use a capture-phase listener to cancel the event before it reaches the component. Call clearSavedData() after a successful response.
const saver = document.querySelector('form-saver');
const form = saver.querySelector('form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
try {
const response = await fetch(form.action, {
method: 'POST',
body: new FormData(form),
});
if (response.ok) saver.clearSavedData();
} catch (error) {
console.error('Form submission failed', error);
}
}, { capture: true });
Attributes and JavaScript Properties
| Attribute / property | Default and behavior |
|---|---|
retain / retain | "". Space-separated field names, or IDs when a name is absent, to retain after submission. |
retain-choice / retainChoice | false. Inserts a retention checkbox when retain contains field names. |
retain-choice-label / retainChoiceLabel | "Store my contact information for later". Sets the checkbox label. |
retain-choice-container / retainChoiceContainer | "". CSS selector for a container within the form. Defaults to placement before the first submit control. |
storage-key / storageKey | form-saver:{method}:{resolvedActionUrl}. Overrides the key used in localStorage. Assign different keys when forms have the same method and action URL. |
Public Methods
Automatic saves use a short debounce, and pending changes are written on pagehide. Use these methods when you need direct control.
| Method | Behavior |
|---|---|
saveFormState() | Saves current field values to localStorage immediately. |
restoreFormState() | Restores saved values to matching fields. |
clearSavedData() | Removes the saved state associated with the current storage key. |
Supported Form Fields
form-saver supports textarea, single-select and multiple-select controls, and inputs other than password, file, submit, button, reset, and image. Password and file values are never saved or restored.
Storage Errors
When a localStorage read, write, or removal fails, form-saver-error fires as a bubbling, composed event. Listen on document before the component is registered to catch errors during initial restoration.
document.addEventListener('form-saver-error', ({ detail }) => {
console.error(`Storage ${detail.operation} failed`, detail.error);
});
Alternatives and Related Resources
- Save Form State to Prevent Data Loss in JavaScript – FormStorage
- Persist Form State To Web Storage On Submit – FormPersistence.js






