Multi-Page Forms
Forma supports multi-page wizard-style forms through the pages property. Pages help organize complex forms into manageable steps.
Structure
{
"pages": [
{
"id": "page-id",
"title": "Page Title",
"description": "Optional instructions",
"visibleWhen": "...",
"fields": ["field1", "field2"]
}
]
}
Page Properties
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique page identifier |
title | string | Yes | Page title shown in navigation |
description | string | No | Instructions or context for the page |
visibleWhen | string | No | FEEL expression to conditionally show page |
fields | array | Yes | Field names to display on this page |
Basic Example
{
"schema": {
"properties": {
"firstName": { "type": "string" },
"lastName": { "type": "string" },
"email": { "type": "string" },
"phone": { "type": "string" },
"message": { "type": "string" }
}
},
"fields": {
"firstName": { "label": "First Name" },
"lastName": { "label": "Last Name" },
"email": { "label": "Email" },
"phone": { "label": "Phone" },
"message": { "label": "Message", "type": "textarea" }
},
"fieldOrder": ["firstName", "lastName", "email", "phone", "message"],
"pages": [
{
"id": "personal-info",
"title": "Personal Information",
"description": "Please provide your contact details",
"fields": ["firstName", "lastName"]
},
{
"id": "contact",
"title": "Contact Details",
"fields": ["email", "phone"]
},
{
"id": "message",
"title": "Your Message",
"fields": ["message"]
}
]
}
Conditional Pages
Use visibleWhen to show pages based on user input:
{
"pages": [
{
"id": "basic-info",
"title": "Basic Information",
"fields": ["name", "email", "accountType"]
},
{
"id": "business-details",
"title": "Business Details",
"visibleWhen": "accountType = \"business\"",
"fields": ["companyName", "taxId", "industry"]
},
{
"id": "preferences",
"title": "Preferences",
"fields": ["newsletter", "notifications"]
}
]
}
When accountType is not "business", the Business Details page is skipped entirely.
Page Navigation
Automatic Navigation
The form renderer handles page navigation automatically:
- Next advances to the next visible page
- Previous returns to the previous page
- Submit appears on the last page
Validation on Navigation
When navigating to the next page:
- All fields on the current page are validated
- Navigation is blocked if validation fails
- Hidden fields are not validated
Page Organization Patterns
Linear Wizard
Simple sequential pages:
{
"pages": [
{ "id": "step-1", "title": "Step 1", "fields": [...] },
{ "id": "step-2", "title": "Step 2", "fields": [...] },
{ "id": "step-3", "title": "Step 3", "fields": [...] }
]
}
Branching Wizard
Different paths based on user choices:
{
"pages": [
{
"id": "select-type",
"title": "Select Type",
"fields": ["applicationType"]
},
{
"id": "individual-details",
"title": "Individual Details",
"visibleWhen": "applicationType = \"individual\"",
"fields": ["ssn", "dateOfBirth"]
},
{
"id": "business-details",
"title": "Business Details",
"visibleWhen": "applicationType = \"business\"",
"fields": ["ein", "incorporationDate"]
},
{
"id": "review",
"title": "Review & Submit",
"fields": ["termsAccepted"]
}
]
}
Grouped Sections
Logical groupings of related information:
{
"pages": [
{
"id": "applicant",
"title": "Applicant Information",
"description": "Tell us about yourself",
"fields": ["fullName", "email", "phone", "address"]
},
{
"id": "employment",
"title": "Employment History",
"description": "Your work experience",
"fields": ["currentEmployer", "jobTitle", "yearsExperience"]
},
{
"id": "education",
"title": "Education",
"description": "Your educational background",
"fields": ["highestDegree", "institution", "graduationYear"]
}
]
}
Field Assignment
Rules
- Each field in
fieldsmust exist in the form'sfieldsobject - A field should only appear on one page
- Fields not assigned to any page are not displayed
Handling Conditional Fields
Conditional fields can be assigned to pages, and they'll show/hide based on their visibleWhen:
{
"fields": {
"hasSpouse": { "label": "Are you married?" },
"spouseName": {
"label": "Spouse Name",
"visibleWhen": "hasSpouse = true"
}
},
"pages": [
{
"id": "family",
"title": "Family Information",
"fields": ["hasSpouse", "spouseName"]
}
]
}
Best Practices
-
Keep pages focused - Each page should cover one topic or section
-
Use descriptive titles - Help users understand where they are in the process
-
Add descriptions - Provide context for what information is needed
-
Order logically - Put dependent questions after their triggers
-
Limit fields per page - 5-7 fields per page is usually ideal
-
Show progress - Most form renderers show a progress indicator
-
Consider conditional pages carefully - Ensure the flow makes sense regardless of which pages are shown
When using conditional pages, test your form by going through every possible path. Make sure the final page is always reachable.