Long forms create abandonment. Users get interrupted, browsers crash, sessions expire. The typical solution stores partial data in localStorage, which creates its own problems: data lives only on that device, disappears when browser storage clears, and sits outside your security perimeter. Form.io takes a different approach. The Save as Draft feature writes partial submissions directly to your MongoDB database, tied to authenticated users, with automatic restoration when they return. Form saving becomes part of your data infrastructure rather than a client-side workaround.
The Architecture of Server-Side Form Saving
Form.io’s draft system works through submission state management. Every submission in Form.io carries a state property that defaults to submitted. The Save as Draft feature creates submissions with state: "draft" instead. These draft submissions store in the same collection as completed submissions, subject to the same permissions, encryption, and backup policies.
The submission JSON for a draft looks like this:
{
"_id": "507f1f77bcf86cd799439011",
"data": {
"firstName": "Sarah",
"lastName": "",
"email": "sarah@example.com"
},
"state": "draft",
"form": "507f1f77bcf86cd799439012",
"owner": "507f1f77bcf86cd799439013",
"created": "2024-01-15T14:32:00.000Z",
"modified": "2024-01-15T14:35:00.000Z"
}
The owner field links the draft to a specific authenticated user. When that user returns to the form, the renderer queries for existing drafts owned by that user and restores the most recent one automatically. This is why anonymous users cannot use Save as Draft: the system needs a user identity to associate with the stored data.
Enabling Automatic Form Saving
The simplest implementation enables periodic auto-save through the saveDraft renderer option. Pass this when creating the form:
Formio.createForm(
document.getElementById('formContainer'),
'https://yourproject.form.io/yourform',
{ saveDraft: true }
);
With this configuration, the renderer saves a draft submission every 5 seconds while the user interacts with the form. If the user navigates away and returns later, the renderer automatically restores their draft. No additional code required.
The save interval is configurable through saveDraftThrottle, specified in milliseconds:
Formio.createForm(
document.getElementById('formContainer'),
'https://yourproject.form.io/yourform',
{
saveDraft: true,
saveDraftThrottle: 10000 // Save every 10 seconds
}
);
Shorter intervals provide better data protection at the cost of more API calls. For forms with many fields or slow network connections, longer intervals reduce server load and prevent save operations from interfering with user input.
Manual Save as Draft with Button Components
For workflows that need explicit user control over form saving, the Button component supports a “Save in State” action. Configure a button with:
- Action: Save in State
- Submission State: draft
When users click this button, the form saves immediately with state: "draft". This approach suits scenarios where users consciously decide to save progress rather than having the system save automatically in the background.
A form with both draft and submit buttons looks like this in JSON schema:
{
components: [
{ type: 'textfield', key: 'firstName', label: 'First Name' },
{ type: 'textfield', key: 'lastName', label: 'Last Name' },
{
type: 'button',
action: 'saveState',
state: 'draft',
key: 'saveDraft',
label: 'Save as Draft'
},
{
type: 'button',
action: 'submit',
key: 'submit',
label: 'Submit'
}
]
}
The “Save in State” action bypasses form validation on the client side. Users can save incomplete forms even when required fields are empty. When they return and click the regular Submit button, validation runs normally.
Draft Restoration Behavior
When a form renders with saveDraft: true, the renderer checks for existing draft submissions owned by the current user. If a draft exists, it restores that data into the form automatically. The user sees their previous progress without any action required.
You can prevent automatic restoration using the skipDraftRestore option:
Formio.createForm(
document.getElementById('formContainer'),
'https://yourproject.form.io/yourform',
{
saveDraft: true,
skipDraftRestore: true
}
);
This is useful when your application manages draft restoration through its own UI, perhaps showing users a list of their drafts and letting them choose which to continue.
The renderer fires events during the draft lifecycle that your application can respond to:
saveDraft: Fired when a draft save completesrestoreDraft: Fired when a draft has been restored into the formsaveDraftError: Fired when draft save failsrestoreDraftError: Fired when draft restoration fails
Authentication
Form saving does not require authenticated users unless you want to associate a draft and its restoration with a specific user.
This can be done through the Formio.setUser() method or through Form.io’s authentication system. When using Form.io’s built-in authentication, the user context propagates automatically. For custom authentication implementations, you need to set the user explicitly:
// Set the authenticated user before rendering the form
Formio.setUser({ _id: 'user123' });
Formio.createForm(
document.getElementById('formContainer'),
'https://yourproject.form.io/yourform',
{ saveDraft: true }
);
One constraint to note: if you explicitly set form.submission after the form renders, draft mode stops working. The renderer interprets an explicit submission assignment as intentional override of any draft state.
Form Saving vs. Offline Mode
Form.io provides two distinct mechanisms for handling incomplete form data, and they serve different purposes.
Save as Draft writes partial submissions to the server while the user is online. It requires network connectivity and authenticated users. Drafts persist in your database indefinitely until the user completes or abandons them.
Offline Mode caches form submissions locally in IndexedDB when the user loses network connectivity. It works for authenticated and anonymous users. Cached submissions sync to the server when connectivity returns.
These can work together. A field worker using your application might have Save as Draft enabled for normal operation, saving progress to the server periodically. If they lose connectivity, Offline Mode captures submissions locally until they reconnect, at which point the sync process pushes data to the server.
The key difference: Save as Draft is a workflow feature for long forms that users complete over multiple sessions. Offline Mode is an infrastructure feature for unreliable network conditions.
Draft Submissions in Multi-Step Wizards
Multi-page form wizards work seamlessly with Save as Draft. The entire wizard submission saves as a single draft, preserving progress across all pages. When users return, they can navigate to any page of the wizard and see their previously entered data.
The automatic save triggers based on form changes, not page navigation. If a user fills out page one, moves to page two, and closes the browser, both pages’ data restore when they return. The saveDraftThrottle interval applies to the entire wizard, not per-page.
For wizards, consider enabling manual draft save buttons on each page. Users often expect explicit “Save and Continue Later” functionality in long multi-step processes. The automatic background save provides protection against accidental data loss, while the manual button gives users confidence that their progress is preserved.
What Happens When Users Submit
When a user clicks the Submit button on a form with an active draft, the submission process:
- Validates the form data against all validation rules
- If validation passes, updates the existing draft submission
- Changes the submission
statefromdrafttosubmitted - Triggers any actions configured on the form (webhooks, emails, etc.)
The draft submission becomes the final submission. Form.io does not create a new submission record; it transitions the existing draft. This means the submission retains its original _id and created timestamp, while the modified timestamp updates.
If you need to track draft history separately from final submissions, enable Submission Revisions in the Security and Compliance package. This creates an audit trail of all changes, including the transition from draft to submitted state.
Querying Draft Submissions
Drafts are normal submissions with a specific state. You can query them through the Form.io API using the state filter:
GET /yourform/submission?state=draft
To find drafts for a specific user:
GET /yourform/submission?state=draft&owner=userId123
Your application might use these queries to build a “My Drafts” dashboard, let users manage multiple in-progress forms, or implement administrative views of abandoned forms.
Exporting form data includes drafts by default. If you need to exclude drafts from exports or reports, filter by state=submitted in your queries or aggregation pipelines.
When Form Saving Creates Problems
Save as Draft introduces considerations your application architecture must address.
Draft accumulation happens when users start forms but never complete them. Unlike localStorage that eventually clears, server-side drafts persist until explicitly deleted. Consider implementing cleanup policies: notify users of abandoned drafts, auto-delete drafts older than a threshold, or provide UI for users to manage their drafts.
Conflicting drafts can occur if a user starts the same form on multiple devices. The renderer restores the most recently modified draft, which may not be the one the user expects. If multi-device usage is common, your application should surface draft management rather than relying on automatic restoration.
Validation inconsistency between draft save and final submit can confuse users. A form saves successfully as draft with missing required fields, then fails validation on submit. Consider using conditional validation or providing clear UI feedback about what additional data is needed for final submission.
Permissions on drafts follow the same rules as submitted data. If your form permissions allow users to read only their own submissions, drafts inherit that restriction. Users cannot access each other’s drafts. For workflows where drafts need sharing (collaborative form completion), you need additional permission configuration.
Form Saving in Workflow Applications
Save as Draft integrates with broader application workflows. Common patterns include:
Approval workflows where forms move through states: draft, submitted, pending review, approved, rejected. The draft state represents user work-in-progress before formal submission. The Approval Workflow tutorial demonstrates this pattern.
Data collection campaigns where users complete complex forms over days or weeks. Insurance applications, grant proposals, compliance questionnaires. Save as Draft lets users chip away at large forms in manageable sessions.
Guided processes that auto populate some fields and require user input for others. Users save drafts as they gather information needed for remaining fields.
What Form Saving Does Not Do
Form saving persists partially completed form data to your database. It does not provide:
Collaboration on drafts: Only the draft owner can access and modify their draft. Shared editing requires additional application logic.
Version history of drafts: Each save overwrites the previous draft state. Enable Submission Revisions if you need draft version tracking.
Anonymous save and return: Users must authenticate. For anonymous workflows, consider Offline Mode or custom localStorage implementations with appropriate security tradeoffs.
Cross-form draft coordination: Each form maintains its own drafts independently. If your workflow spans multiple forms, your application coordinates draft state across them.
Related Resources
- Save as Draft documentation covers implementation details
- Form Renderer options lists all draft-related configuration
- Submissions documentation explains submission states and lifecycle
- Offline Mode describes local caching for disconnected scenarios
- API Documentation covers submission querying and filtering
- Multi-Page Form Wizards explains wizard behavior with drafts
- Authentication Support details user authentication requirements
