Form Builder
The Form Builder is the core of FormForge. It provides a visual editor for creating and managing forms within the Umbraco backoffice. This guide covers form creation, multi-page layouts, conditional logic, grid positioning, revision history, and duplication.
Creating Forms
Every form in FormForge starts with a handful of core properties that identify it across the system.
Form Properties
| Property | Description |
|---|---|
| Name | A human-readable label shown in the backoffice. Can contain spaces and special characters. |
| Alias | A URL-safe, unique identifier for the form. Used in API endpoint paths (/api/forms/{alias}/submit) and when referencing the form from a ViewComponent (<vc:form-forge alias="contact-us" />). Must be lowercase, alphanumeric, and may contain hyphens. No two forms can share the same alias. |
| Description | An optional internal note. Not rendered on the front end — useful for documenting the form’s purpose for other editors. |
Choose your alias carefully. While it can be changed later, any existing API integrations or ViewComponent references that use the old alias will break. Treat aliases like URL slugs — short, descriptive, and stable.
Form Folders
As your form library grows, use folders to keep things organized. Folders are purely cosmetic — they group forms in the backoffice tree but have no effect on aliases, API paths, or rendering. You can nest folders and drag forms between them at any time.
Sort Order
Each form has a numeric sort order that controls its position within a folder. Lower numbers appear first. When multiple forms share the same sort order, they fall back to alphabetical sorting by name.
Archiving
Forms can be archived instead of deleted. An archived form is hidden from the main list and excluded from API endpoints, but its data (submissions, revisions, settings) is preserved. You can unarchive a form at any time to restore it to active duty.
Archive seasonal or campaign forms when they’re no longer needed rather than deleting them. This keeps your submission data intact for future reporting.
Multi-Page Forms
FormForge supports splitting a form across multiple pages, which is useful for long or complex forms like onboarding wizards, multi-step checkouts, or detailed surveys.
Page Structure
Internally, a form’s schema is stored as Schema.Pages — an ordered array of page objects. Each page has:
- Title(optional) — displayed as a heading above the page’s fields. If omitted, no heading is rendered.
- Fields — the list of field definitions that belong to this page.
Even single-page forms use this structure — they simply have one page in the array.
Managing Pages
In the form builder UI:
- Click the “+ Add page” button to append a new page.
- Use the arrow buttons on each page header to reorder pages.
- Remove a page by clicking its delete action. Fields on a deleted page are removed with it — move them first if you want to keep them.
Step Indicator
You can configure how users see their progress through a multi-page form by setting the step indicator mode:
| Mode | Value | Behavior |
|---|---|---|
| None | "none" | No visual indicator is shown. Users navigate blind — suitable for very short forms (2 pages). |
| Numbered | "numbered" | Displays numbered step pills, e.g. Step 1 of 3. Best for forms where each page represents a distinct section. |
| Progress | "progress" | Shows a progress bar with a percentage. Ideal for longer forms where the exact step number matters less than overall completion. |
Navigation and Validation
Multi-page forms render Previous and Next buttons for navigation. The Submit button only appears on the last page.
Validation is per-page: when the user clicks Next, only the fields on the current page are validated. The user cannot advance until all visible, required fields on the current page pass validation. This prevents users from being overwhelmed by errors from fields they haven’t seen yet.
Combine multi-page forms with conditional logic to create adaptive wizards. For example, a first page can ask “Are you an individual or a business?” and subsequent pages can show different fields based on the answer.
Conditional Logic
Conditional logic lets you show or hide fields based on other fields’ values. This keeps forms concise by only presenting questions that are relevant to the user’s situation.
How It Works
Any field can have a VisibleWhen condition attached to it. A condition is a simple rule composed of three parts:
- Field Alias — the alias of the field to evaluate.
- Operator— how to compare the field’s value.
- Value — the expected value (not required for all operators).
Available Operators
| Operator | Description | Requires Value |
|---|---|---|
equals | Case-insensitive match against the target value | Yes |
notequals | Case-insensitive non-match against the target value | Yes |
contains | Substring match (case-insensitive) | Yes |
isempty | True when the field value is null or whitespace | No |
isnotempty | True when the field has any non-whitespace value | No |
Behavior When Hidden
When a field’s VisibleWhen condition evaluates to false, the following happens:
- The field is not rendered on the page — it is completely removed from the DOM, not just visually hidden.
- The field is not validated — required rules and other validators are skipped for hidden fields.
- Any submitted values for hidden fields are silently droppedon the server. This prevents data poisoning attacks where a malicious user manually submits values for fields they shouldn’t see.
Client-Side Evaluation
Conditions evaluate in real-time on the client as the user types or selects values. There is no round-trip to the server — fields appear and disappear instantly as conditions are met or unmet.
Example
Suppose you have a Dropdown field with alias typeand options “Individual” and “Business”. You want to show a Textfield called “Company Name” only when the user selects “Business”.
Configure the “Company Name” field’s condition as:
- Field Alias:
type - Operator:
equals - Value:
Business
Now the “Company Name” field remains hidden until “Business” is selected, and any value entered into it is discarded if the user switches back to “Individual”.
Grid Layout
By default, every field occupies the full width of the form. The grid layout feature lets you place fields side by side in a two-column grid, which is useful for related field pairs like first and last name, or email and phone number.
Width Property
Each field has a Width property with two possible values:
| Value | Behavior |
|---|---|
"full" | The field spans the entire row (default). It always starts on a new line. |
"half" | The field takes one column in a two-column layout. Two consecutive half-width fields sit side by side. |
CSS Grid Implementation
The form renderer uses CSS Grid with the rule:
grid-template-columns: repeat(2, minmax(0, 1fr));A "full" width field spans both columns (grid-column: span 2), while a "half" width field spans one column. This means you can freely mix full and half-width fields in any order — the grid handles the layout automatically.
Common Patterns
- First Name + Last Name — both set to
"half", they appear as two equal columns. - Email + Phone — both
"half", side by side. - Address Line 1 —
"full", spanning the entire width. - City + Postal Code — both
"half", side by side.
On narrow viewports (mobile), the grid automatically collapses to a single column so half-width fields stack vertically. You don’t need to configure any responsive breakpoints — it just works.
Revisions
FormForge automatically tracks every meaningful change to a form through an immutable revision history. This gives you a complete audit trail and the ability to roll back to any previous state.
Automatic Snapshots
Every time you save a form, FormForge compares the current schema and settings against the last saved version using JSON equality. If anything has actually changed — a field added, a label edited, a setting toggled — a new revision is created. If nothing changed (e.g. you clicked Save without making edits), no revision is created. This keeps the history clean and meaningful.
What Revisions Track
Each revision stores:
- Version number — an auto-incrementing integer (1, 2, 3, ...).
- Form name — the name of the form at the time of the revision.
- Schema — the complete page and field structure.
- Settings — all form-level settings (submission behavior, notifications, etc.).
- Timestamp — when the revision was created.
- Created by — the Umbraco user who made the change.
Viewing Revisions
Open the Revisions panel in the form builder to see a chronological list of all revisions. Each entry shows the version number, timestamp, and the user who created it.
Restoring a Revision
You can restore any revision to revert the form to that point in time. When you restore:
- A new revision of the current state is created first (so you never lose your current work).
- The form’s schema and settings are then overwritten with the values from the selected revision.
This means restoring is always safe — you can restore a restore if needed.
Immutability
Revisions are append-only. Once created, a revision cannot be edited or deleted individually. Revisions are only removed when the parent form itself is permanently deleted.
Before making large structural changes to a form (like reorganizing pages or removing fields), note the current version number. If anything goes wrong, you can restore to that version in one click.
Duplication
Duplicating a form creates an independent copy that you can modify without affecting the original. This is useful for creating variations of an existing form (e.g. a localized version) or using a form as a template.
How It Works
Click the Duplicate action on any form. FormForge performs a deep clone of the entire form, including:
- All schema data (pages, fields, conditions, grid widths).
- All settings (submission behavior, notifications, workflows).
ID Regeneration
During duplication, all internal identifiers are regenerated — page IDs, field IDs, and workflow IDs all receive fresh values. This ensures the duplicate is fully independent and won’t conflict with the original in the database or API.
Naming
The duplicate receives an auto-generated name and alias based on the original:
- Name:
"{Original Name} (Copy)" - Alias:
{original}-copy
If a form with that alias already exists, a numeric suffix is appended: {original}-copy-2, {original}-copy-3, and so on.
Duplication does not copy submissions or revision history. The new form starts with a clean slate — zero submissions and a single initial revision.