Skip to main content
View as Markdown

Form Success & Error Handling

The submission commits and the request returns. What happens on screen next is a product decision, not a technical one: a support ticket wants a reference number, a newsletter signup wants to stay put and accept another address, a checkout wants to move on.

onSuccess and onError make that decision declarative:

forms:
  - id: 1
    name: contact
    title: Contact Sales
    submitTo: { table: leads }
    fields:
      - { kind: table-field, column: email, required: true }
    onSuccess:
      type: successPage
      title: Thank you
      message: We received your message and will reply within one business day.
    onError:
      type: message
      message: Something went wrong saving your request. Please try again.

onSuccess Types

onSuccess is a union discriminated by type. Each type carries its own properties.

type Properties Behavior
successPage title, message, buttonLabel, buttonHref, actions[], showSummary Replaces the form with a success screen.
redirect url (required), delaySeconds Navigates away. delaySeconds defaults to 2; 0 navigates immediately.
reset message, preserveFields[] Clears the form for another submission, keeping the listed fields' values.
toast message (required), variant (success | info) Shows a transient notification and leaves the filled form in place.
message message (required) Replaces the form with an inline message.

Omit onSuccess entirely and the form falls back to a success toast reading "Submitted." — a sane default, but rarely the one you want in production.

reset is the type to reach for on a single-page form a submitter fills repeatedly. On a multi-step layout it clears the answers but does not return the submitter to the first step, so prefer successPage with a reset action there.

Success-Page Actions

A successPage can offer the submitter a next move. Each entry in actions[] renders as a button:

onSuccess:
  type: successPage
  title: Ticket received
  message: Our team has been notified.
  showSummary: true
  actions:
    - { label: Submit another, action: reset }
    - { label: Back to help centre, action: navigate, url: /help }
Property Description Default
label Button text. Supports $t: keys. Required.
action reset returns the empty form; navigate sends the submitter to url. Required.
url Navigation target. Required for navigate, ignored by reset.

showSummary: true lists the submitted values below the message. It skips hidden fields and applies per-field read permissions, so a summary never shows a submitter something they were not allowed to read back.

Template Variables

Success copy and redirect targets can quote the submission that just happened. Three variables are substituted at submit time, in title, message and url alike:

Variable Resolves to
$submission.id The ledger row id. Empty when submitTo.storeSubmission is false.
$record.id The bound-table row id. Empty when the form has no submitTo.table.
$record.<column> A column of the inserted row — but only one the submitter themselves supplied.
onSuccess:
  type: redirect
  url: /thank-you?ref=$submission.id
  delaySeconds: 0

Values substituted into a url are percent-encoded, so an email address survives the query string intact. The $record.<column> restriction is deliberate: server-computed and privileged columns are never exposed through a redirect URL, however tempting the shortcut.

onError

onError covers whole-submission failures — the write was rejected, the request did not complete.

Property Description Default
type toast, message (inline), or errorPage (full page). Required.
message Body text. Supports $t: keys. Required.
title Heading, used by errorPage.
variant error or warning. Only meaningful for type: toast. error

Omitted, it falls back to a toast reading "Submission failed."

Per-field validation errors are a different channel. An invalid email or a missing required value comes back as a fieldErrors list and is rendered inline against the offending input — onError fires alongside it as the whole-form summary, not instead of it.

  • Submissions — the dual write that has to commit before onSuccess runs.
  • Form Fields — the per-field read permissions showSummary honors.
  • Multi-Step Forms — what "after the last step" means for these types.
  • Forms Overview — where onSuccess and onError sit in the full form schema.

Last updated July 27, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.

Built with Sovrium