form-schema-runtime

Supported schema nodes, fields, validation rules, and visibility conditions.

Documentation pages
On this page
  1. FormSchema
  2. Sections and Groups
  3. Field Names
  4. Field Properties
  5. Labels, Placeholders, and Help Text
  6. Disabled and Readonly
  7. Required Fields
  8. Initial Values
  9. Options
  10. Field-Level Validation Rules
  11. Conditional Visibility
  12. Field Types
  13. text
  14. email
  15. number
  16. password
  17. textarea
  18. select
  19. checkbox
  20. radio

Schema Reference

Schemas are plain JSON-compatible objects that describe fields, sections, labels, validation, and simple conditional visibility. Schema strings are treated as untrusted text and are rendered with DOM APIs, not as HTML.

FormSchema

const schema: FormSchema = {
  id: "profile-form",
  title: "Profile form",
  description: "Update account profile data.",
  submitLabel: "Save profile",
  resetLabel: "Clear",
  fields: []
};
PropertyRequiredDescription
idyesStable schema identifier used for generated DOM IDs.
fieldsyesTop-level fields and sections.
titlenoForm heading.
descriptionnoSafe text rendered below the title.
submitLabelnoSubmit button label. Defaults to Submit.
resetLabelnoReset button label. Defaults to Reset.

Sections and Groups

Sections group fields visually and semantically. They render as native fieldset elements with a legend.

PropertyRequiredDescription
typeyesMust be section.
titleyesVisible legend text.
fieldsyesChild fields or nested sections.
descriptionnoSafe explanatory text below the legend.
idnoStable identifier used when deriving section paths.
visibleWhennoVisibility rule applied to the section and all its children.
{
  type: "section",
  title: "Contact details",
  description: "How the team can reach this customer.",
  fields: [
    {
      type: "email",
      name: "email",
      label: "Email",
      required: true
    }
  ]
}

Sections do not produce values. Their child fields do.

Field Names

Each field needs a unique name within the form schema:

{
  type: "text",
  name: "firstName",
  label: "First name"
}

The name is used in values, dirty/touched state, validation errors, and submit payloads.

Field Properties

Every built-in and custom value-producing field uses FieldSchema.

PropertyRequiredDescription
typeyesBuilt-in field type or a custom type with a registered renderer.
nameyesUnique value key within the form.
labelyesVisible label for the control.
idnoStable identifier used when deriving normalized field metadata. Defaults from name.
visibleWhennoOne visibility condition or a simple AND array.
placeholdernoNative placeholder for text-like controls; never a label replacement.
helpTextnoDescriptive text wired through aria-describedby.
requirednoEnables required validation and native required state.
disablednoApplies the native disabled state.
readonlynoApplies to text-like native controls.
optionsfor select and radioNon-empty list of unique { label, value } options.
defaultValuenoInitial field value when no form-level initial value is provided.
minLength, maxLengthnoString length limits.
min, maxnoNumeric range limits.
patternnoJavaScript regular expression source used for validation.
validatorsnoNames of registered synchronous custom validators.
validationMessagesnoPer-rule overrides for built-in validation messages.

Labels, Placeholders, and Help Text

{
  type: "text",
  name: "companyName",
  label: "Company name",
  placeholder: "Example Corp",
  helpText: "Use the registered legal name."
}

Labels are associated with native controls. Placeholders are optional hints and must not replace labels. Help text is referenced by aria-describedby.

Disabled and Readonly

{
  type: "text",
  name: "sourceSystem",
  label: "Source system",
  readonly: true,
  defaultValue: "Identity Governance"
}
{
  type: "text",
  name: "accessWindow",
  label: "Access window",
  disabled: true,
  defaultValue: "Business hours only"
}

readonly applies to text-like native controls. disabled renders the native disabled attribute.

Required Fields

{
  type: "email",
  name: "email",
  label: "Email",
  required: true
}

Required fields render visible required text and native required attributes where appropriate.

Initial Values

Field-level defaults:

{
  type: "select",
  name: "accountType",
  label: "Account type",
  defaultValue: "business",
  options: [
    { label: "Consumer", value: "consumer" },
    { label: "Business", value: "business" }
  ]
}

Form-level initial values:

createForm({
  container,
  schema,
  initialValues: {
    accountType: "business"
  }
});

initialValues override field defaults.

Options

select and radio fields require options:

options: [
  { label: "Low", value: "low" },
  { label: "High", value: "high" }
]

Option values must be unique within a field.

Built-in select and radio controls read values through the native DOM and therefore store the selected value as a string after user interaction. Prefer string option values when value type stability matters.

Field-Level Validation Rules

Supported built-in rules:

  • required
  • minLength
  • maxLength
  • min
  • max
  • pattern
  • email validation for email fields
{
  type: "text",
  name: "employeeId",
  label: "Employee ID",
  required: true,
  pattern: "^[A-Z]{2}-[0-9]{5}$",
  validationMessages: {
    pattern: "Employee ID must look like IT-12345."
  }
}

Custom validators are referenced by name:

{
  type: "text",
  name: "taxCode",
  label: "Tax code",
  validators: ["taxCode"]
}

Validators are registered from application code through createForm({ validators }).

validationMessages supports these keys:

  • required
  • minLength
  • maxLength
  • min
  • max
  • pattern
  • email
  • number

These keys override built-in messages only. Custom validators return their own message strings.

Conditional Visibility

Use visibleWhen for small, declarative conditions:

{
  type: "text",
  name: "companyName",
  label: "Company name",
  required: true,
  visibleWhen: {
    field: "accountType",
    equals: "enterprise"
  }
}

Supported operators:

  • equals
  • notEquals
  • includes
  • exists
  • simple AND arrays
visibleWhen: [
  { field: "accountType", equals: "enterprise" },
  { field: "country", exists: true }
]

Hidden fields are not validated.

Field Types

text

Use text for short free-text input.

{
  type: "text",
  name: "fullName",
  label: "Full name"
}

Validation example:

{
  type: "text",
  name: "fullName",
  label: "Full name",
  required: true,
  minLength: 2,
  maxLength: 80
}

email

Use email for email addresses. Email fields receive built-in email validation.

{
  type: "email",
  name: "email",
  label: "Email",
  required: true
}

number

Use number for numeric input.

{
  type: "number",
  name: "amount",
  label: "Amount",
  min: 1,
  max: 250000
}

Empty number fields are stored as null.

password

Use password for password-like native controls.

{
  type: "password",
  name: "temporaryPassword",
  label: "Temporary password",
  minLength: 12
}

Do not put real secrets into demo schemas, logs, or examples. Password values are still normal form values in browser memory.

textarea

Use textarea for longer text.

{
  type: "textarea",
  name: "notes",
  label: "Notes",
  maxLength: 500
}

select

Use select when one option should be chosen from a compact list.

{
  type: "select",
  name: "department",
  label: "Department",
  required: true,
  options: [
    { label: "Finance", value: "finance" },
    { label: "Operations", value: "operations" }
  ]
}

checkbox

Use checkbox for boolean values.

{
  type: "checkbox",
  name: "approvalConfirmed",
  label: "Manager approval is attached",
  required: true
}

Unchecked checkboxes store false.

radio

Use radio for a small list of mutually exclusive visible choices.

{
  type: "radio",
  name: "accessLevel",
  label: "Access level",
  required: true,
  options: [
    { label: "Read only", value: "read" },
    { label: "Standard contributor", value: "write" },
    { label: "Administrator", value: "admin" }
  ]
}

Radio groups render with role="radiogroup" and a labelled group.