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