Form Field Types Reference
Complete reference of all supported form field types in ApprovalML
Form Field Types Reference
Complete reference for all supported form field types in ApprovalML workflows.
Quick Reference
| Type | Category | Description |
|---|---|---|
text | Text | Single-line text input |
textarea | Text | Multi-line text input |
email | Text | Email with format validation |
richtext | Text | WYSIWYG rich text editor |
number | Numeric | Integer or decimal input |
currency | Numeric | Money amount with symbol |
date | Date & Time | Calendar date picker |
dropdown / select | Selection | Single-choice dropdown |
multiselect | Selection | Multi-choice dropdown |
radio | Selection | Radio buttons or button group |
checkbox | Selection | Boolean toggle |
autocomplete | Selection | Search-as-you-type with data source |
file_upload / file | File & Media | File or image attachment (use accept: ".pdf" for PDF-only) |
image | File & Media | Image display (logos, headers) |
signature | File & Media | Digital signature capture |
line_items | Advanced | Repeating row table |
autonumber | Advanced | Sequential auto-generated number |
hidden | Advanced | Non-displayed metadata field |
Text Input Fields
text
Single-line text input for short responses.
- name: employee_name
type: text
label: "Full Name"
required: true
placeholder: "Enter your full name"
min_length: 2
max_length: 100Common Uses: Names, titles, short descriptions, IDs, reference codes
textarea
Multi-line text input for longer responses.
- name: description
type: textarea
label: "Description"
required: true
rows: 4
placeholder: "Enter detailed description..."
min_length: 10
max_length: 1000Common Uses: Descriptions, comments, justifications, policy notes
email
Email address input with built-in format validation.
- name: contact_email
type: email
label: "Email Address"
required: true
placeholder: "user@company.com"Validation: Automatically enforces user@domain.tld format.
Common Uses: Contact emails, approver addresses, notification recipients
richtext
WYSIWYG rich text editor with HTML formatting and image embedding.
- name: detailed_description
type: richtext
label: "Detailed Description"
required: false
placeholder: "Enter formatted text with images..."Features:
- Bold, italic, underline, heading formatting
- Bullet lists and numbered lists
- Hyperlinks
- Image upload (auto-converted to base64)
- Stored as HTML
Storage: Saved to S3 at companies/{company_id}/workflows/{workflow_id}/instances/{instance_id}/richtext/{field_name}.html
Common Uses: Policy documents, detailed proposals, formatted instructions
Numeric Fields
number
Numeric input accepting integers or decimals.
- name: quantity
type: number
label: "Quantity"
required: true
placeholder: "0"
min_value: 1
max_value: 1000Properties:
| Property | Description |
|---|---|
min_value | Minimum allowed value |
max_value | Maximum allowed value |
Common Uses: Quantities, counts, percentages, ratings, days
currency
Money amount with automatic currency symbol formatting.
- name: total_amount
type: currency
label: "Total Amount"
required: true
currency: "USD"
min_value: 0.01
max_value: 1000000Properties:
| Property | Description | Default |
|---|---|---|
currency | ISO 4217 currency code | "USD" |
min_value | Minimum amount | — |
max_value | Maximum amount | — |
readonly | Prevent editing (use with formula) | false |
calculated | Marks field as computed | false |
formula | Expression to calculate value | — |
Supported currencies: USD, EUR, GBP, JPY, SGD, IDR, MYR, AUD, and all ISO 4217 codes.
Common Uses: Purchase amounts, budgets, salaries, invoice totals, line-item subtotals
Date & Time Fields
date
Calendar date picker.
- name: start_date
type: date
label: "Start Date"
required: true
min_date: "2024-01-01"
max_date: "2025-12-31"Properties:
| Property | Description |
|---|---|
min_date | Earliest selectable date (YYYY-MM-DD) |
max_date | Latest selectable date (YYYY-MM-DD) |
Common Uses: Deadlines, start/end dates, travel dates, expiry dates
Selection Fields
dropdown / select
Single-choice dropdown with predefined or dynamic options. dropdown and select are aliases — use whichever reads more naturally.
- name: department
type: dropdown
label: "Department"
required: true
options:
- label: "Engineering"
value: "engineering"
- label: "Sales"
value: "sales"
- label: "Marketing"
value: "marketing"Common Uses: Departments, categories, statuses, priorities, countries
multiselect
Multi-choice dropdown — user can select one or more options.
- name: required_skills
type: multiselect
label: "Required Skills"
required: false
options:
- label: "JavaScript"
value: "javascript"
- label: "Python"
value: "python"
- label: "Java"
value: "java"Common Uses: Skills, tags, cost centers, systems affected, roles
radio
Radio button group for single selection. Supports a compact button-style layout.
- name: urgency
type: radio
label: "Urgency Level"
required: true
display_as: "buttons" # Optional: renders as styled button group
options:
- label: "Low"
value: "low"
- label: "Medium"
value: "medium"
- label: "High"
value: "high"
- label: "Critical"
value: "critical"Properties:
| Property | Description |
|---|---|
display_as | "buttons" for button-group style; omit for classic radio circles |
Common Uses: Priority levels, approval types, yes/no, rating scales
checkbox
Single boolean toggle for true/false responses.
- name: agree_to_terms
type: checkbox
label: "I agree to the terms and conditions"
required: trueCommon Uses: Agreements, acknowledgements, opt-ins, feature flags
autocomplete
Search-as-you-type field backed by a dynamic data source. Requires a configured data source — static options are not supported.
- name: employee
type: autocomplete
label: "Select Employee"
required: true
options:
data_source:
source_id: "src_employees"
value_field: "id"
label_field: "name"
display: "{name} - {department}"
search:
min_length: 2 # Start searching after 2 characters
debounce_ms: 300 # Delay before querying (default: 300ms)Properties:
| Property | Description |
|---|---|
options.data_source.source_id | Registered data source ID |
options.data_source.value_field | Field used as the stored value |
options.data_source.label_field | Field shown in the dropdown |
options.data_source.display | Template for display text (e.g. "{name} - {dept}") |
search.min_length | Characters required before search fires (default: 2) |
search.debounce_ms | Milliseconds to wait between keystrokes (default: 300) |
Common Uses: Employee picker, product search, customer lookup, location select
File & Media Fields
file_upload / file
File attachment field. file_upload and file are aliases.
- name: receipt
type: file_upload
label: "Upload Receipt"
required: true
accept: ".pdf,.jpg,.png"
multiple: false
max_file_size: "5MB"PDF-only upload:
- name: contract_document
type: file_upload
label: "Contract PDF"
required: true
accept: ".pdf,application/pdf"
max_file_size: "10MB"
help_text: "Upload the signed contract in PDF format"Mobile camera capture:
- name: site_photo
type: file_upload
label: "Take a Photo"
accept: "image/*"
capture: "environment" # "environment" = rear camera, "user" = front cameraProperties:
| Property | Description |
|---|---|
accept | Comma-separated MIME types or extensions (e.g. ".pdf,.docx") |
multiple | Allow more than one file (true/false) |
capture | Force camera on mobile: "environment" or "user" |
max_file_size | Human-readable size limit (e.g. "5MB", "10MB") |
Common Uses: Receipts, invoices, contracts, photos, supporting documents
signature
Digital signature capture field. Pulls the user's stored signature from their profile.
- name: requestor_signature
type: signature
label: "Your Signature"
required: true
help_text: "Sign to confirm your submission"Test mode: Automatically uses /images/samplesignature.png — no real signatures needed during development or demos.
Production: Captures the logged-in user's saved signature (text, drawn, or uploaded). Stored securely with the instance record.
Common Uses: Contract execution, policy acknowledgement, expense certification, approval sign-off
image
Display-only image field for logos, header images, and visual branding.
- name: company_logo
type: image
label: "Company Logo"
source: "company" # Pulls from company settings
show_label: false
readonly: true
height: 64px
placement: inline
position: leftProperties:
source: Where to load the image from"company"- Company logo from settings"form"- From form data field- URL string - Direct image URL
height: CSS height value (e.g.,"64px","100px")placement:"inline"for horizontal placementposition:"left","right", or"center"show_label: Set tofalseto hide the label
Common Uses: Company branding in headers, product images, logos, decorative elements
Advanced Fields
line_items
Dynamic repeating-row table. Users can add and remove rows; each row contains the configured item_fields. Supports calculated columns within rows.
- name: items
type: line_items
label: "Order Items"
required: true
min_items: 1
max_items: 20
item_fields:
- name: description
type: text
label: "Item Description"
required: true
- name: qty
type: number
label: "Qty"
required: true
min_value: 1
- name: unit_price
type: currency
label: "Unit Price"
required: true
currency: "USD"
- name: total
type: currency
label: "Total"
readonly: true
calculated: true
formula: "qty * unit_price"
currency: "USD"Supported field types inside item_fields: text, number, currency, dropdown, select, textarea, autocomplete
Properties:
| Property | Description | Default |
|---|---|---|
min_items | Minimum required rows | 0 |
max_items | Maximum allowed rows (hard cap: 100) | — |
item_fields | Column definitions (required) | — |
Summary totals: Place a currency field outside line_items with formula: "sum(items.column_name)" to sum a column across all rows.
- name: grand_total
type: currency
label: "Grand Total"
readonly: true
calculated: true
formula: "sum(items.total)"
currency: "USD"Common Uses: Purchase orders, invoices, expense reports, timesheets, material lists
autonumber
Automatically generates a sequential, unique reference number at form submission. The number is assigned server-side — it is never editable by the user. Each workflow field maintains its own independent counter per company.
- name: po_number
type: autonumber
label: "PO Number"
prefix: "PO-"
pad_length: 5 # → PO-00001, PO-00042, PO-10000
start_value: 1Properties:
| Property | Required | Description | Default |
|---|---|---|---|
prefix | ❌ No | Text prepended to the number (e.g. "PO-", "EXP-", "INV-") | "" |
pad_length | ❌ No | Zero-pad the number to this many digits (e.g. 5 → 00042) | No padding |
start_value | ❌ No | First number in the sequence | 1 |
How it works:
- The field renders as read-only with an "Auto-generated on submit" placeholder while the user fills out the form.
- On submission the server atomically increments the counter for
(company_id, workflow_id, field_name)and formats the number as{prefix}{zero-padded number}. - The generated value (e.g.
PO-00001) is stored in the form data and visible to all approvers throughout the workflow.
Thread safety: Uses an atomic INSERT … ON CONFLICT DO UPDATE … RETURNING to guarantee uniqueness under concurrent submissions.
Database table: workflow_field_sequences (company_id, workflow_id, field_name, last_value)
Common Uses: Purchase order numbers, expense claim numbers, invoice numbers, ticket IDs, contract references
Examples:
# PO-00001, PO-00002, …
prefix: "PO-"
pad_length: 5
# EXP-2026-001, EXP-2026-002, … (manually include year in prefix)
prefix: "EXP-2026-"
pad_length: 3
# Plain numbers: 1, 2, 3, …
# (omit prefix and pad_length)hidden
Non-displayed field for storing metadata or pre-computed values. Included in form data but never shown to the user.
- name: source_system
type: hidden
default: "HR-Portal"Common Uses: Tracking codes, system IDs, computed values passed between steps, version markers
Field Properties Reference
Universal Properties
Every field type accepts these properties:
| Property | Required | Description |
|---|---|---|
name | ✅ Yes | Unique snake_case identifier within the form |
type | ✅ Yes | Field type (see table above) |
label | ✅ Yes | Display label shown to the user |
required | ❌ No | Whether the field must be filled (true/false, default false) |
placeholder | ❌ No | Hint text shown inside empty input |
help_text | ❌ No | Explanatory text shown below the field |
default_value | ❌ No | Pre-filled value |
readonly | ❌ No | Prevent user edits (combine with formula for calculated fields) |
Validation Properties
Set directly on the field (not nested under validation:):
- name: amount
type: number
min_value: 0
max_value: 100000
- name: notes
type: text
min_length: 10
max_length: 500
pattern: "^[A-Za-z0-9 ]+$" # Regex
- name: receipt
type: file_upload
max_file_size: "5MB"Note: A
validation:block in YAML is also accepted and is automatically unwrapped to the direct properties above.
Formula / Calculated Fields
Combine readonly: true, calculated: true, and formula to derive a value from other fields:
- name: total
type: currency
label: "Total"
readonly: true
calculated: true
formula: "qty * unit_price" # Inside line_items
currency: "USD"
- name: grand_total
type: currency
label: "Grand Total"
readonly: true
calculated: true
formula: "sum(items.total)" # Sum a line_items column
currency: "USD"Supported operations: +, -, *, /, sum(), avg(), min(), max()
Conditional Display
Show or hide a field based on another field's value:
- name: other_reason
type: textarea
label: "Please specify"
conditional:
show_if: "reason == 'other'"Visual Styling
style: "warning" # "warning" | "danger" | "success" | "info"Dynamic Options (Data Sources)
Static Options
options:
- label: "Option 1"
value: "opt1"
- label: "Option 2"
value: "opt2"Compatible with: dropdown, select, multiselect, radio
Dynamic Data Source
options:
data_source:
source_id: "src_employees" # Registered data source
value_field: "id" # Stored value
label_field: "name" # Display text
display: "{name} - {dept}" # Optional rich display templateCompatible with: autocomplete (required), dropdown, select, multiselect
Field Type Selection Guide
| I need to collect… | Use |
|---|---|
| A name, title, or short text | text |
| A long description or note | textarea |
| An email address | email |
| Formatted text with images | richtext |
| A count or quantity | number |
| A monetary amount | currency |
| A calendar date | date |
| One choice from a list | dropdown or select |
| Multiple choices from a list | multiselect |
| A true/false toggle | checkbox |
| One choice displayed as buttons | radio with display_as: "buttons" |
| A searchable entity (employee, product…) | autocomplete |
| An uploaded document or image | file_upload or file |
| A captured signature | signature |
| Repeating rows (purchase items, expenses…) | line_items |
| An auto-generated sequential reference number | autonumber |
| Hidden tracking metadata | hidden |
Best Practices
✅ Do:
- Use descriptive
namevalues (e.g.employee_name, notfield1) - Set
required: trueonly for fields that are truly mandatory - Choose the most specific type (use
emailnottextfor email addresses) - Use
dropdownfor any field with ≤ 20 fixed options - Add
placeholderandhelp_textto guide users - Put
autonumberas the first field so it appears at the top of the form - Use
min_items: 1online_itemswhen at least one row is required
❌ Don't:
- Use
textwhen a specific type (email,date,currency) exists - Make every field
required— it frustrates users - Define
autocompletewith static options (usedropdowninstead) - Forget validation bounds on
numberandcurrencyfields - Use complex
formulaexpressions without testing them
Complete Example
form:
fields:
# Auto-generated reference number
- name: expense_number
type: autonumber
label: "Expense Claim No."
prefix: "EXP-"
pad_length: 5
# Requestor details
- name: employee_name
type: text
label: "Employee Name"
required: true
- name: employee_email
type: email
label: "Email Address"
required: true
# Category selection
- name: category
type: dropdown
label: "Expense Category"
required: true
options:
- label: "Travel"
value: "travel"
- label: "Meals"
value: "meals"
- label: "Equipment"
value: "equipment"
- label: "Other"
value: "other"
# Conditional: only shown when category is "other"
- name: other_category
type: text
label: "Specify Category"
conditional:
show_if: "category == 'other'"
# Date and urgency
- name: expense_date
type: date
label: "Expense Date"
required: true
- name: urgency
type: radio
label: "Urgency"
required: true
display_as: "buttons"
options:
- label: "Normal"
value: "normal"
- label: "Urgent"
value: "urgent"
# Line items with calculated totals
- name: items
type: line_items
label: "Expense Items"
required: true
min_items: 1
max_items: 30
item_fields:
- name: description
type: text
label: "Description"
required: true
- name: amount
type: currency
label: "Amount"
required: true
currency: "USD"
- name: total_amount
type: currency
label: "Total Amount"
readonly: true
calculated: true
formula: "sum(items.amount)"
currency: "USD"
# Justification and receipt
- name: justification
type: textarea
label: "Business Justification"
required: true
rows: 3
- name: receipt
type: file_upload
label: "Receipt(s)"
required: true
accept: ".pdf,.jpg,.jpeg,.png"
multiple: true
max_file_size: "10MB"
# Signature and hidden metadata
- name: requestor_signature
type: signature
label: "Employee Signature"
required: true
- name: submitted_via
type: hidden
default: "web-form"Related Documentation
Version: 1.1 Last Updated: 2026-03-13 Status: Production Ready ✅