Form schema API reference
Team Forms stores each form layout as a Form.io compatible JSON schema. This reference covers the supported authoring surface used by the Team Forms builder and AI assistant.
The builder may retain additional Form.io defaults and internal properties. When editing source JSON, preserve properties you do not understand and add only properties that are relevant to the required behaviour.
Form schema
Section titled “Form schema”The schema has the following top-level properties:
| Property | Type | Description |
|---|---|---|
display | "form" | "wizard" | Selects a standard single-page form or a multi-page wizard. |
components | component array | Contains the form’s top-level components. Wizard schemas contain one top-level panel for each page. |
settings | object, optional | Stores form-level renderer settings. Preserve existing settings unless you are changing a documented form-level option. |
The form title, icon, custom CSS, PDF options, response-title template, and published state are form configuration rather than component schema properties.
{ "display": "form", "components": [ { "type": "textfield", "key": "requesterName", "label": "Requester name", "validate": { "required": true } }, { "type": "button", "key": "submit", "label": "Submit", "action": "submit", "disableOnInvalid": false } ]}Common component properties
Section titled “Common component properties”Every component requires a supported type and a unique, descriptive camel-case key. Most input components also require a concise label. Only include optional properties when they change the component’s behaviour.
| Property | Type | Description |
|---|---|---|
type | string | The exact component type from the component catalogue below. |
key | string | Unique camel-case identifier used in response data and JavaScript, such as requesterName. It must also satisfy the reserved-name rules below. |
label | string | User-facing caption for an input. Panels use title for their visible heading. |
title | string | Visible heading for a panel, including a wizard page. |
description | string | Supporting text displayed with the component. |
tooltip | string | Additional guidance displayed on demand. |
placeholder | string | Example or hint displayed inside an empty input. |
prefix | string | Content displayed before the input value. |
suffix | string | Content displayed after the input value. |
customClass | string | Static CSS class names added to the component. Do not include a leading dot. |
defaultValue | any | Static value used when the component has no response value. The value must match the component’s data shape. |
multiple | boolean | Allows multiple values where the component supports it. |
hidden | boolean | Hides the component while retaining it in the schema. |
disabled | boolean | Prevents the user from changing the value. |
clearOnHide | boolean | Clears the stored value when the component becomes hidden. |
persistent | boolean or string | Controls whether the value is included in saved response data. Use the builder defaults unless there is a specific requirement. |
protected | boolean | Marks response data as protected. Do not enable it without a specific requirement. |
unique | boolean | Requests uniqueness validation for the value. Do not assume it replaces workflow or server-side uniqueness guarantees. |
tableView | boolean | Controls whether the field is included in default response tables. |
input | boolean | Identifies a value-producing component. Layout and content components normally set this to false; input components normally inherit true. |
modalEdit | boolean | Opens editing in a modal where supported. Prefer the normal inline experience unless requested. |
autofocus | boolean | Focuses the component when the form opens. Only one component should normally use this. |
redrawOn | string | Component key whose changes should redraw this component. Use "data" to redraw for any response-data change. |
refreshOn | string | Component key whose changes should refresh a component’s data. |
validateOn | "change" | "blur" | Selects when validation runs. |
validate | object | Contains validation rules described below. |
errorLabel | string | Alternate name used in validation messages. |
pdfVisibility | "visible" | "hidden" | "hideIfEmpty" | Controls whether the component is rendered in generated PDFs. This is independent of browser-form visibility. |
Component keys and reserved names
Section titled “Component keys and reserved names”The builder calls key the component’s Property Name. It is used in response data, Handlebars paths, executable JavaScript, email suggestions, and connector schemas, so changing it after responses exist can break those references.
A key must:
- contain only letters, numbers, underscores, dots, and dashes;
- start and end with a letter, number, or underscore;
- be unique and preferably use descriptive camelCase; and
- not equal a registered component type, case-insensitively, unless it is the current component’s own type.
The reserved names are the component type values in this reference, including names such as textfield, email, select, content, panel, columns, datagrid, file, spSelect, and approval.
| Component | Key | Valid | Reason |
|---|---|---|---|
textfield | requesterEmail | Yes | Descriptive and not a component type. |
email | email | Yes | A component may use its own type as its key. |
textfield | email | No | email is another registered component type. |
number | dataGrid | No | Reserved-name comparison is case-insensitive, so it conflicts with datagrid. |
textfield | requester name | No | Spaces are not allowed. |
For generated forms, prefer domain-specific keys instead of generic component names even where the own-type exception would allow them.
Validation properties
Section titled “Validation properties”| Property | Applies to | Description |
|---|---|---|
validate.required | most inputs | Requires a non-empty response. |
validate.minLength | text inputs | Minimum number of characters. |
validate.maxLength | text inputs | Maximum number of characters. |
validate.minWords | text areas | Minimum word count. |
validate.maxWords | text areas | Maximum word count. |
validate.min | number, currency, date/time | Minimum accepted value. |
validate.max | number, currency, date/time | Maximum accepted value. |
validate.pattern | text inputs | Regular-expression pattern the value must match. |
validate.custom | advanced | JavaScript that assigns a boolean or message to valid. Use the exact development context supplied by the AI assistant. |
validate.unique | supported inputs | Requests a unique value. Confirm that the intended storage and submission path supports this behaviour. |
Component catalogue
Section titled “Component catalogue”Text and numeric inputs
Section titled “Text and numeric inputs”| Type | Use | Important properties |
|---|---|---|
textfield | Short general-purpose text. | Common text properties and validate. |
textarea | Multi-line or long text. | rows, autoExpand, editor, and text validation. Use a plain textarea unless rich text is requested. |
email | Email address. | Built-in email validation plus common text properties. Prefer this over textfield for email. |
url | Web address. | Built-in URL validation plus common text properties. |
phoneNumber | Telephone number. | Common text properties and an input mask configured through the builder when needed. |
number | Numeric input. | delimiter, decimalLimit, requireDecimal, and validate.min or validate.max. |
currency | Monetary value. | currency, decimalLimit, delimiter, and numeric validation. |
Choice inputs
Section titled “Choice inputs”| Type | Use | Important properties |
|---|---|---|
checkbox | One boolean choice. | defaultValue is normally true or false. |
radio | One choice displayed as radio options. | values, inline, and defaultValue. |
selectboxes | Multiple choices displayed as checkboxes. | values, inline, and defaultValue. |
select | Drop-down or searchable choice. | dataSrc, data, valueProperty, template, multiple, and refreshOn. |
tags | Free-form or suggested tags. | storeas, delimiter, and maxTags. |
survey | Several related questions sharing one response scale. | questions and values. |
Radio and select-box options use values:
{ "type": "radio", "key": "priority", "label": "Priority", "values": [ { "label": "Low", "value": "low" }, { "label": "Medium", "value": "medium" }, { "label": "High", "value": "high" } ]}A static drop-down uses dataSrc: "values" and data.values:
{ "type": "select", "key": "department", "label": "Department", "dataSrc": "values", "data": { "values": [ { "label": "Finance", "value": "finance" }, { "label": "Operations", "value": "operations" } ] }}A survey contains stable values for both its questions and response scale:
{ "type": "survey", "key": "serviceRatings", "label": "Service ratings", "questions": [ { "label": "Response time", "value": "responseTime" }, { "label": "Communication", "value": "communication" } ], "values": [ { "label": "Poor", "value": "poor" }, { "label": "Good", "value": "good" }, { "label": "Excellent", "value": "excellent" } ]}Date and time inputs
Section titled “Date and time inputs”| Type | Use | Important properties |
|---|---|---|
datetime | Date-only, time-only, or combined date/time input. | enableDate, enableTime, defaultToCurrentDate, defaultDate, format, datePicker, and timePicker. |
time | Time-only input. | inputType, format, and common input properties. |
Use datetime with enableTime: false for a date-only field. To default it to today, set both defaultToCurrentDate: true and defaultDate: "moment().format()".
{ "type": "datetime", "key": "requestDate", "label": "Request date", "enableTime": false, "defaultToCurrentDate": true, "defaultDate": "moment().format()"}The older day component can appear in existing schemas, but datetime with enableTime: false is preferred for new forms.
Team Forms and advanced inputs
Section titled “Team Forms and advanced inputs”| Type | Use | Important properties |
|---|---|---|
address | Structured address lookup. | provider and enableManualMode. Preserve provider-specific configuration from the builder. |
user | Microsoft 365 user picker. | usersSource is "teamMembers", "organization", or "specificUsers"; it may also use specificUsers, selectFields, sampleItem, refreshOn, and clearOnCopy. The AI assistant normally uses "organization" and must never invent directory users. |
signature | Drawn or typed signature. | enableTyping; set it to true for newly generated signatures. |
file | File or image upload. | storage, multiple, fileTypes, fileMaxSize, showImageEditor, and webcam. Team Forms uploads use storage: "indexeddb"; do not enable webcam automatically. |
sketchPad | Mark up a predefined image. | file contains the background image. Use an existing or placeholder image rather than inventing base64 image data. |
location | Select or capture a map location. | map.defaultCenterSource, map.showResetLocationButton, map.height, map.zoom, and map controls. |
barcodeScanner | Scan a barcode or QR code with the device camera. | Common input properties; the stored value contains the scanned value and format. |
submissionNumber | Display the form’s sequential submission number. | padding controls leading zeros. This value is assigned during submission and cannot be relied on by live calculated fields. |
hidden | Store data without displaying an input. | defaultValue, calculateValue, customDefaultValue, and persistence settings. |
spSelect | Select an object from an existing Team Forms data source. | dataSourceId, template, labelProperty, selectFields, removeDuplicates, sortBy, sortDirection, and filterQuery. Pair a directly supplied custom template with labelProperty: { "label": "🛠 Custom", "value": "custom" }. Never set valueProperty. |
approval | Add an approval step that may contain approver fields. | components, exact approvers, chooseApprover, revokers, dependsOn, and action-specific email wrappers. Do not add approvalStatus manually. |
Example Team Forms user picker:
{ "type": "user", "key": "lineManager", "label": "Line manager", "usersSource": "organization"}Example image upload:
{ "type": "file", "key": "supportingImages", "label": "Supporting images", "storage": "indexeddb", "multiple": true, "showImageEditor": true, "webcam": false}See User component schema for user sources, projections, and stored directory objects. See Data-source component schema for the exact spSelect projection and duplicate-removal order, source-type mapping, filters, and sharepointFilePreview. See Approval component schema for exact approver objects, dependencies, conditional approvals, stored status, submit behaviour, and notification templates.
Content and layout components
Section titled “Content and layout components”| Type | Use | Important properties and child shape |
|---|---|---|
content | Rich explanatory content. | html contains the markup and input is false. Inline <svg> markup is not supported by the Form.io renderer; use an <img> whose src is an embedded data:image/svg+xml URI instead. |
htmlelement | Basic HTML element in existing schemas. | tag, content, attrs, and input: false. Prefer content for rich instructions. |
panel | Titled visual section or wizard page. | title, components, collapsible, collapsed, and scrollToTop. |
well | Visually grouped child components. | components. |
fieldset | Semantically grouped child components. | legend or label, plus components. |
tabs | Tabbed groups. | components contains tab objects, each with label, key, and components. |
columns | Responsive horizontal layout. | Each column uses size: "md" (xs, sm, md, lg, or xl), numeric width and currentWidth values from 1–12, and components. Widths in a row must total 12. |
table | Fixed rows and columns used for layout. | rows contains arrays of cells; each cell has components. |
pdfPageBreak | Starts a new page in generated PDF output. | Normally input: false. It does not create a browser-form page. |
sharepointFilePreview | Displays an existing SharePoint file preview while online. | dataSourceId, height (minimum 200), input: false, and pdfVisibility: "hidden". The source type must be sharepoint-file-preview. |
Example two-column layout:
{ "type": "columns", "key": "requesterDetails", "label": "Requester details", "columns": [ { "size": "md", "width": 6, "currentWidth": 6, "components": [] }, { "size": "md", "width": 6, "currentWidth": 6, "components": [] } ]}Structured data components
Section titled “Structured data components”| Type | Use | Important properties and data shape |
|---|---|---|
container | Groups children and nests their response data under the container key. | components. Use a panel or fieldset when nesting response data is not required. |
datagrid | Repeatable rows with a fixed set of child fields. | components, initEmpty, reorder, addAnother, responsiveLayout, responsiveBreakpoint, and row validation. Calculations inside a row can read row. |
datamap | User-defined key/value pairs. | valueComponent defines the value editor. Use sparingly; a datagrid is usually clearer. |
Set responsiveLayout: true on new data grids so each row stacks vertically on smaller screens. responsiveBreakpoint controls when this happens and supports sm, md, or lg; use md unless another breakpoint is specifically required.
See Nested and repeating component schema for exact response paths, row calculations, fixed rows, containers, Data Maps, and Handlebars iteration.
editgrid and tree can appear in existing advanced forms. They have more complex editing and nested-data behaviour and should not be generated or reconfigured without explicit requirements and relevant existing schema context.
PDF visibility
Section titled “PDF visibility”Every supported visual component can control its generated-PDF visibility independently from its browser-form visibility:
pdfVisibility | Behaviour |
|---|---|
visible | Allow the component to render in the PDF. Normal conditional logic still applies. This is the default. |
hidden | Never render the component in the PDF. |
hideIfEmpty | Render the component only when it or its child components contain a value. |
The static hidden property controls browser-form visibility and does not imply that the component is hidden in the PDF. For example, a calculated summary can be hidden from the browser form but deliberately included in the PDF:
{ "type": "content", "key": "pdfSummary", "html": "<p>Submitted by {{ data.requesterName }}</p>", "hidden": true, "pdfVisibility": "visible", "input": false}Use pdfVisibility: "hidden" for browser-only instructions, interactive controls, or online previews. Use hideIfEmpty for optional questions or sections that should not leave blank space in the generated document. Conditional rules such as conditional and customConditional continue to be evaluated in PDF rendering.
Actions
Section titled “Actions”| Type | Use | Important properties |
|---|---|---|
button | Submit or custom action. | action, theme, disableOnInvalid, event, and onChange. Standard forms end with action: "submit"; wizard navigation supplies the final submit action. Team Forms hides normal submit actions while a visible approval supplies its own actions. |
Wizard schema
Section titled “Wizard schema”Each top-level wizard component is a panel representing a page. Set scrollToTop: true on each page. Do not add a submit button to the last page because the wizard renderer supplies its own navigation and final submit action.
{ "display": "wizard", "components": [ { "type": "panel", "key": "requestDetailsPage", "title": "Request details", "scrollToTop": true, "components": [] }, { "type": "panel", "key": "reviewPage", "title": "Review", "scrollToTop": true, "components": [] } ]}Executable properties
Section titled “Executable properties”Executable properties contain JavaScript statements evaluated by Form.io and Team Forms. Property names and mutable output variables are exact. Do not derive them from the labels displayed by the builder.
| Builder setting | Schema property | Required output | Behaviour |
|---|---|---|---|
| Calculated Value | calculateValue | value | Recalculates the component value when relevant form data changes. Never use calculatedValue; that is not the schema setting. |
| Custom Default Value | customDefaultValue | value | Computes the initial value without continually overwriting later user input. |
| Custom Conditional | customConditional | show | Shows or hides the component by assigning a boolean. |
| Dynamically Disabled | customDisabled | disabled | Enables or disables the component by assigning a boolean. |
| Custom Validation | validate.custom | valid | Assigns true, false, or a validation message. |
| Change handler | onChange | none | Runs after the component value changes. Use only when a calculated or conditional property is not suitable. |
| Dynamic custom class | customClassAdvanced | customClass | Computes CSS class names. Static class names belong in customClass. |
| Custom select data | data.custom | values | Computes or loads a select’s available options. |
| JavaScript logic trigger | logic.trigger.javascript | result | Determines whether a logic trigger runs. |
| Logic value action | logic.actions.value | value | Computes the value assigned by a logic action. |
| Logic schema action | logic.actions.schemaDefinition | schema | Computes a schema fragment applied by a logic action. |
Calculated value example:
{ "type": "number", "key": "lineTotal", "label": "Line total", "calculateValue": "value = (Number(data.quantity) || 0) * (Number(data.unitPrice) || 0)"}Inside a datagrid row, use row for values in that row:
{ "type": "number", "key": "lineTotal", "label": "Line total", "calculateValue": "value = (Number(row.quantity) || 0) * (Number(row.unitPrice) || 0)"}Conditional visibility example:
{ "type": "textarea", "key": "rejectionReason", "label": "Rejection reason", "customConditional": "show = data.decision === 'rejected'"}Executable schema values contain JavaScript statements, not a wrapping function and not TypeScript. When using the AI assistant, it loads the available Team Forms and Form.io declarations for the exact component and schema property before changing executable code.
Dynamic labels
Section titled “Dynamic labels”Labels and content can interpolate response data with expressions such as {{ data.requesterName }}. They do not evaluate arbitrary JavaScript. Set redrawOn to the referenced component key, or to "data" when any response change should refresh the content.
{ "type": "content", "key": "requestSummary", "html": "<p>Request for {{ data.requesterName }}</p>", "redrawOn": "requesterName", "input": false}Context-dependent components
Section titled “Context-dependent components”The following component types can appear in Team Forms but depend on advanced product state. Preserve them when editing existing forms. Do not invent their configuration without the required context.
| Type | Context required |
|---|---|
recaptcha | Published-form and provider configuration. |
password | A specific requirement for masked text and an understood persistence policy. |
editgrid | Explicit row-editing requirements and existing nested schema context. |
tree | Explicit recursive data requirements and existing nested schema context. |
Related guides
Section titled “Related guides”- Calculated fields
- Calculated values versus custom default values
- Code examples
- Conditionally hide or show components
- Dynamically disable components
- Data Grid component
- Container component
- Component response values
- User component schema
- Nested and repeating component schema
- Data-source component schema
- Approval component schema
- Email template syntax
- PDF visibility
- Use the AI assistant