Skip to main content

Fields

The fields property defines how each form field is displayed and behaves. Each key must match a property name in your schema.

Field Definition

{
"fields": {
"fieldName": {
"label": "Display Label",
"description": "Help text",
"placeholder": "Placeholder text",
"type": "text",
"visibleWhen": "...",
"requiredWhen": "...",
"enabledWhen": "...",
"validations": [...],
"options": [...]
}
}
}

Common Properties

PropertyTypeDescription
labelstringDisplay label shown above the field
descriptionstringHelp text shown below the field
placeholderstringPlaceholder text inside the input
typestringField type override (see Field Types)
defaultValueanyInitial value when form loads (must match type)
readonlyWhenFEELExpressionWhen this field is read-only
variantstringPresentation variant hint
variantConfigRecord<string, unknown>Variant-specific configuration

Default Values

Use defaultValue to pre-populate a field when the form loads:

{
"country": {
"label": "Country",
"type": "select",
"defaultValue": "us",
"options": [
{ "value": "us", "label": "United States" },
{ "value": "ca", "label": "Canada" }
]
},
"quantity": {
"label": "Quantity",
"type": "integer",
"defaultValue": 1
},
"subscribe": {
"label": "Subscribe to newsletter",
"type": "boolean",
"defaultValue": true
}
}

Resolution order (highest priority wins):

  1. initialData prop passed at runtime
  2. defaultValue from the field definition
  3. Implicit type defaults (booleans default to false)

Notes:

  • defaultValue must match the field's schema type (string for text/select, number for number/integer, boolean for boolean)
  • Display fields cannot have defaultValue
  • For array item fields, defaultValue is applied each time a new item is added

Field Types

The type property determines how the field is rendered. If omitted, it's inferred from the schema.

Text Input Types

TypeDescriptionSchema Type
textSingle-line text inputstring
textareaMulti-line text inputstring
emailEmail input with validationstring (format: email)
urlURL inputstring (format: uri)
passwordPassword input (masked)string
{
"bio": {
"label": "Biography",
"type": "textarea",
"placeholder": "Tell us about yourself..."
}
}

Numeric Types

TypeDescriptionSchema Type
numberDecimal number inputnumber
integerWhole number inputinteger
{
"quantity": {
"label": "Quantity",
"type": "integer",
"description": "Enter a whole number"
}
}

Boolean Type

TypeDescriptionSchema Type
booleanCheckbox or toggleboolean
{
"subscribe": {
"label": "Subscribe to newsletter",
"type": "boolean"
}
}

Date Types

TypeDescriptionSchema Type
dateDate pickerstring (format: date)
datetimeDate and time pickerstring (format: date-time)
{
"appointmentDate": {
"label": "Preferred Date",
"type": "date"
}
}

Selection Types

TypeDescriptionSchema Type
selectDropdown selectionstring with enum
multiselectMultiple selectionarray of strings
{
"country": {
"label": "Country",
"type": "select",
"options": [
{ "value": "us", "label": "United States" },
{ "value": "ca", "label": "Canada" },
{ "value": "uk", "label": "United Kingdom" }
]
}
}

Complex Types

TypeDescriptionSchema Type
arrayRepeatable group of fieldsarray
objectNested field groupobject
computedRead-only calculated valueN/A
displayRead-only display contentN/A

Display Fields

Display fields show read-only content such as headings, metrics, or alerts. They have no user input and are not included in form data.

{
"header": {
"type": "display",
"label": "Section Header",
"content": "Please review the following information."
},
"totalDisplay": {
"type": "display",
"label": "Order Total",
"source": "total",
"format": "currency"
}
}
PropertyTypeDescription
contentstring | undefinedStatic text content
sourcestring | undefinedComputed field name to display dynamically
formatstring | undefinedDisplay format hint (e.g., "currency")

For rendering details, see Display Fields in the forma-react docs.

Options

For select and multiselect fields, define available choices:

{
"options": [
{ "value": "option1", "label": "Option One" },
{ "value": "option2", "label": "Option Two" }
]
}

Option Properties

PropertyTypeDescription
valuestring | numberValue stored when selected
labelstringDisplay text shown to user
visibleWhenstringFEEL expression to conditionally show option

Conditional Options

Show options based on other field values:

{
"plan": {
"label": "Plan",
"type": "select",
"options": [
{ "value": "free", "label": "Free" },
{ "value": "pro", "label": "Pro" },
{
"value": "enterprise",
"label": "Enterprise",
"visibleWhen": "companySize > 100"
}
]
}
}

Array Fields

For repeatable groups of fields, use type: "array" with itemFields:

{
"schema": {
"properties": {
"contacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" }
}
}
}
}
},
"fields": {
"contacts": {
"label": "Contacts",
"type": "array",
"minItems": 1,
"maxItems": 5,
"itemFields": {
"name": { "label": "Name" },
"email": { "label": "Email" }
}
}
}
}

Array Properties

PropertyTypeDescription
itemFieldsobjectField definitions for each array item
minItemsintegerMinimum required items
maxItemsintegerMaximum allowed items

Object Fields

For nested data structures, use type: "object". Object fields group nested properties defined in the schema — unlike array fields, they do not use itemFields:

{
"schema": {
"properties": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zipCode": { "type": "string" }
}
}
}
},
"fields": {
"address": {
"label": "Address",
"type": "object"
},
"address.street": { "label": "Street" },
"address.city": { "label": "City" },
"address.zipCode": { "label": "ZIP Code" }
},
"fieldOrder": ["address"]
}

Access nested values in expressions with dot notation: address.city, address.zipCode.

Field Order

The fieldOrder array determines the display order:

{
"fieldOrder": ["firstName", "lastName", "email", "phone"]
}

Fields not in fieldOrder are not displayed.

Type Inference

In the TypeScript type system, type is a required property on FieldDefinition. At runtime, if type is omitted, it can be inferred from the schema:

SchemaInferred Type
{ "type": "string" }text
{ "type": "string", "format": "email" }email
{ "type": "string", "format": "date" }date
{ "type": "string", "enum": [...] }select
{ "type": "integer" }integer
{ "type": "number" }number
{ "type": "boolean" }boolean
{ "type": "array" }array