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
| Property | Type | Description |
|---|---|---|
label | string | Display label shown above the field |
description | string | Help text shown below the field |
placeholder | string | Placeholder text inside the input |
type | string | Field type override (see Field Types) |
defaultValue | any | Initial value when form loads (must match type) |
readonlyWhen | FEELExpression | When this field is read-only |
variant | string | Presentation variant hint |
variantConfig | Record<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):
initialDataprop passed at runtimedefaultValuefrom the field definition- Implicit type defaults (booleans default to
false)
Notes:
defaultValuemust 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,
defaultValueis 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
| Type | Description | Schema Type |
|---|---|---|
text | Single-line text input | string |
textarea | Multi-line text input | string |
email | Email input with validation | string (format: email) |
url | URL input | string (format: uri) |
password | Password input (masked) | string |
{
"bio": {
"label": "Biography",
"type": "textarea",
"placeholder": "Tell us about yourself..."
}
}
Numeric Types
| Type | Description | Schema Type |
|---|---|---|
number | Decimal number input | number |
integer | Whole number input | integer |
{
"quantity": {
"label": "Quantity",
"type": "integer",
"description": "Enter a whole number"
}
}
Boolean Type
| Type | Description | Schema Type |
|---|---|---|
boolean | Checkbox or toggle | boolean |
{
"subscribe": {
"label": "Subscribe to newsletter",
"type": "boolean"
}
}
Date Types
| Type | Description | Schema Type |
|---|---|---|
date | Date picker | string (format: date) |
datetime | Date and time picker | string (format: date-time) |
{
"appointmentDate": {
"label": "Preferred Date",
"type": "date"
}
}
Selection Types
| Type | Description | Schema Type |
|---|---|---|
select | Dropdown selection | string with enum |
multiselect | Multiple selection | array of strings |
{
"country": {
"label": "Country",
"type": "select",
"options": [
{ "value": "us", "label": "United States" },
{ "value": "ca", "label": "Canada" },
{ "value": "uk", "label": "United Kingdom" }
]
}
}
Complex Types
| Type | Description | Schema Type |
|---|---|---|
array | Repeatable group of fields | array |
object | Nested field group | object |
computed | Read-only calculated value | N/A |
display | Read-only display content | N/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"
}
}
| Property | Type | Description |
|---|---|---|
content | string | undefined | Static text content |
source | string | undefined | Computed field name to display dynamically |
format | string | undefined | Display 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
| Property | Type | Description |
|---|---|---|
value | string | number | Value stored when selected |
label | string | Display text shown to user |
visibleWhen | string | FEEL 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
| Property | Type | Description |
|---|---|---|
itemFields | object | Field definitions for each array item |
minItems | integer | Minimum required items |
maxItems | integer | Maximum 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:
| Schema | Inferred 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 |