Form Validation and Visibility
Configure field-level and form-level validation rules and conditional field visibility directly in the builder — without writing event handler code. This page covers the builder UI approach to validation and show/hide logic. For the programmatic API (calling validateForm, reading form.errors, and handling the onSubmit event) see Validation, Methods & Events.
Scope of This Page
This page covers what you configure on each field in the form's Fields editor — the rules that determine whether a field is valid and whether it is visible. Think of it as the declarative, no-code layer. The companion page covers the imperative API that lets you trigger validation programmatically and respond to events in action chains.
Note: Select a field in the Form block's Fields editor. Each field has a Validation section and a Visibility property in its inspector. The settings described here are field-level — they appear per field, not on the form as a whole.
Validation Rules
Required Rule
Mark a field as required by toggling the Required switch on, or supply a binding expression that evaluates to a boolean. Using an expression lets you make a field conditionally required — it is only required when the expression is true.
| Setting | Value | Effect |
required (static) | true | Field is always required. An error is shown if the field is empty at validation time. |
required (expression) | {{ form.values.country == "IN" }} | Field is required only when the expression returns true — in this example, only when the country field is set to India. The required indicator (*) appears or disappears dynamically. |
Pattern Rule (Regex)
Validate a text or number field against a regular expression by setting the Pattern rule. Provide the regex as a string (without leading/trailing slashes). An optional custom error message is shown when the pattern does not match.
Pattern validation examples
// Phone number — 10 digits pattern: ^[0-9]{10}$ errorMessage: "Phone must be exactly 10 digits" // Email format pattern: ^[^\s@]+@[^\s@]+\.[^\s@]+$ errorMessage: "Enter a valid email address" // GST Number (India) pattern: ^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$ errorMessage: "Enter a valid 15-character GSTIN"
Custom Validation (JS Expression)
For logic that cannot be expressed as a simple regex, use a custom validation expression. The expression has access to the field's current value via value and the whole form's current values via form.values. Return true to pass, false to fail with the default error message, or a string to fail with a custom message.
Custom validation expressions
// Minimum purchase amount {{ value >= 100 ? true : "Minimum order amount is ₹100" }} // End date must be after start date (cross-field) {{ new Date(value) > new Date(form.values.startDate) ? true : "End date must be after the start date" }} // Password confirmation {{ value === form.values.password ? true : "Passwords do not match" }} // File size limit (file upload field) {{ !value || value.size < 5 * 1024 * 1024 ? true : "File must be under 5 MB" }}
Tip: Returning a custom error string from a validation expression is the correct way to implement cross-field validation in the builder. The expression on field B can reference form.values.fieldA — when field A's value changes, field B's validation re-runs automatically.
Validation Timing
Control when validation runs on a field by setting its Validate on property:
| Timing | When it fires | Best for |
onChange | Every time the field's value changes — as the user types or makes a selection | Instant feedback fields like password strength or phone number format |
onBlur | When the user leaves the field (focus moves elsewhere) | Most fields — validates after the user has finished entering, not while typing |
onSubmit | Only when the form's submit action is triggered | Fields where early validation would distract — e.g. one-time codes, confirmations |
Error Display
By default, validation errors appear as red inline text directly below each field. Two additional display modes are available at the form level:
Inline (default) — error message appears beneath the field that failed.
Form-level summary — a summary of all errors appears at the top or bottom of the form as a single block. Enable this in the form's Content → Error Display settings.
Both — inline errors on each field plus a summary block. Useful for long forms where the first error may be scrolled off screen.
Warning: When a field is hidden by a visibility rule (see below), its validation rules do not run — the form submits without requiring a value for that field. This is intentional and correct: do not add required rules to fields that may be hidden, unless you also account for the visibility condition in the required expression.
Visibility Rules
Show or hide individual fields based on binding expressions. Open a field's inspector and set its Visibility to an expression. When the expression is truthy the field is shown; when falsy it is hidden and excluded from validation and form data.
Simple Visibility
Conditionally show a field based on another field's value
// Show "Tax Number" field only when country is India Visibility: {{ form.values.country == "IN" }} // Show "Other reason" text field only when "Other" is selected in a dropdown Visibility: {{ form.values.cancellationReason == "other" }} // Show "Company Name" field only when account type is Business Visibility: {{ form.values.accountType == "business" }} // Hide a field until a prior field has a value Visibility: {{ !!form.values.firstName }}
Role-Based Visibility
Show admin-only fields based on user role
// Show "Internal Notes" only for admin users Visibility: {{ userContext.roles.includes("admin") }} // Show "Override Price" field only for managers Visibility: {{ userContext.department === "sales" && userContext.level >= 5 }}
Combining Visibility and Required
The most robust pattern is to make a field's required expression mirror its visibility expression. This prevents scenarios where a hidden field blocks form submission because it is marked always-required.
Correct pattern: visibility and required share the same condition
// "GST Number" field visibility: {{ form.values.country == "IN" }} required: {{ form.values.country == "IN" }} // The field appears and is required only for Indian users. // For other countries it is hidden AND not required — clean submit guaranteed.
Form-Level Validation Configuration
At the form level (not per-field), you can configure how the form handles overall validation state:
| Setting | Location | Description |
validateOnMount | Content → Interactions | When enabled, validation runs immediately when the form loads — errors appear before the user has interacted with any field. Use sparingly; it can be jarring for new records. |
errorDisplay | Content → Interactions | Choose between inline (beneath each field), summary (a block at the top or bottom), or both. |
scrollToFirstError | Content → Interactions | When enabled, the page automatically scrolls to the first invalid field after a failed submit. Recommended for long forms. |