Skip to main content
View as Markdown

Form Fields

A form's fields array is an ordered list of field definitions rendered top to bottom. Each field is one of five kinds, discriminated by a kind property. Table-bound fields inherit their type and validation from a table column; standalone fields are typed inline; calculation, section, and signature fields cover computed values, dividers, and signatures.

forms:
  - id: 1
    name: signup
    title: Create your account
    submitTo: { table: users }
    fields:
      - { kind: table-field, column: email, required: true }
      - { kind: standalone, name: newsletter, inputType: checkbox, label: Subscribe to updates }

Field Kinds

Kind Description
table-field Bound to a column on submitTo.table. Type, validation, and persistence flow from the table schema; the form overrides only display.
standalone Typed inline via inputType; not persisted to a column directly. Use for forms that route only to automations or the ledger.
calculation Read-only computed value derived from other fields via a {{fieldName}} formula. Renders no input.
section Visual divider with an optional heading and description. Renders no input.
signature Captures a hand-drawn or typed signature.

Common Field Properties

Every input-bearing field kind (table-field, standalone, calculation, signature) shares a common base.

Property Description
label Label shown to the submitter. Supports $t: i18n keys.
placeholder Placeholder text shown when the field is empty.
helpText Help text rendered below the field.
required Boolean. When true, the field must have a value. For conditional requiredness use requiredWhen.
readOnly Boolean. Renders the field display-only.
hidden Boolean. Hides the field from the UI but still submits it (server-only value).
defaultValue Literal value, or a $query.{name} / $user.{prop} reference resolved at render time.
visibleWhen Conditional visibility rule. See Conditional Logic.
requiredWhen Conditional required rule (same shape as visibleWhen).
disabledWhen Conditional disabled rule (same shape as visibleWhen).
permissions Per-field read permission. When the requesting role is excluded, the value is redacted from admin exports and per-submission detail.

Table-Bound Fields

A kind: table-field references a column on the form's submitTo.table. The field type, validation, and persistence all come from the table schema — the form supplies only display concerns plus, for attachment columns, upload options.

Property Description
column Column name on submitTo.table. Required.
accept Comma-separated MIME types or extensions for attachment columns.
maxFileSize Maximum size (bytes) per uploaded file (attachment columns).
maxFiles Maximum number of files for multiple-attachments columns.
dropZone Render a drag-and-drop zone alongside the file picker.
fields:
  - kind: table-field
    column: subject
    label: What can we help with?
    placeholder: Briefly describe the issue
  - kind: table-field
    column: priority
    helpText: Urgent issues are triaged first

Attachment columns (single-attachment, multiple-attachments) automatically render a file input. See File Uploads for the upload pipeline and bucket binding.

Standalone Fields

A kind: standalone field is typed inline via inputType and is not written to a table column directly. It is ideal for forms that route to an automation or live only in the submission ledger.

Property Description
name Field name unique within the form (^[a-zA-Z][a-zA-Z0-9_-]*, ≤64 chars). Required.
inputType Control type (see below). Required.
options { value, label } choices for select / multi-select / radio.
accept Accepted MIME types for attachment input.
maxFiles Max files for attachment input.
maxFileSize Maximum size (bytes) per uploaded file.
dropZone Render a drag-and-drop zone alongside the file picker.

Available inputType values: short-text, long-text, email, url, phone, number, date, datetime, select, multi-select, checkbox, radio, rating, attachment.

fields:
  - kind: standalone
    name: rating
    inputType: rating
    label: How was your experience?
    required: true
  - kind: standalone
    name: source
    inputType: select
    label: How did you hear about us?
    options:
      - { value: search, label: Search engine }
      - { value: referral, label: Referral }
      - { value: social, label: Social media }

Calculation, Section & Signature Fields

Kind Key properties
calculation name, formula (references other fields via {{name}}), optional format (number / currency / percent / text). Read-only.
section Optional heading, description, and a whole-section visibleWhen rule. Renders no input.
signature name. Captures a hand-drawn or typed signature.
fields:
  - { kind: standalone, name: quantity, inputType: number, label: Quantity }
  - { kind: standalone, name: unit_price, inputType: number, label: Unit price }
  - kind: calculation
    name: total
    label: Total
    formula: '{{quantity}} * {{unit_price}}'
    format: currency

Prefill

The top-level prefill map seeds field values at render time. Keys are form field names; values are either a literal default or a reference:

Reference Resolves to
$query.{name} A URL query-string parameter (e.g. $query.utm_source).
$user.{prop} A property of the authenticated user (e.g. $user.email). Silently dropped on public forms with no session.
$parent.{path} A field of the parent record — only valid for inline-relationship forms (see below).
forms:
  - id: 1
    name: lead-capture
    title: Request a demo
    submitTo: { table: leads }
    prefill:
      utm_source: $query.utm_source
      utm_campaign: $query.utm_campaign
    fields:
      - { kind: table-field, column: email, required: true }
      - { kind: standalone, name: utm_source, inputType: short-text, hidden: true }
      - { kind: standalone, name: utm_campaign, inputType: short-text, hidden: true }

Inline Relationship Create

When a form is embedded inside a parent record's detail page (e.g. a "+ New ticket" button on a Project page), the $parent.{path} prefill source ties the new child back to its parent automatically. This is configured on the page form control via inlinePrefill.

Property Description
prefill Field-name → prefill-source map (same $query / $user / $parent union).
lockPrefill When true, the prefilled fields are hidden and cannot be overridden (still validated server-side). Defaults to false.
forms:
  - id: 1
    name: new-ticket
    submitTo: { table: tickets }
    fields:
      - { kind: table-field, column: title, required: true }
      - { kind: table-field, column: project_id }
      - { kind: table-field, column: reporter_id }

pages:
  - id: 1
    name: project-detail
    path: /portal/projects/:id
    components:
      - type: form
        formRef: new-ticket
        inlinePrefill:
          prefill:
            project_id: $parent.id # locked to the current project
            reporter_id: $user.id
          lockPrefill: true

On submit, the engine revalidates parent existence to defend against stale $parent references. Both single and multi-relationship columns are supported.