The UI Schema defines how to render a dynamic form — the layout structure, controls, conditional visibility rules, and custom options. It follows the JSON Forms UI Schema specification.
Structure
A UI Schema is a tree of elements. Each element has a type that determines how it behaves:
- Layouts — Container elements that organize other elements
- Controls — Elements that render input fields bound to schema properties
{
"type": "VerticalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/firstName",
"label": "First Name"
},
{
"type": "Control",
"scope": "#/properties/lastName",
"label": "Last Name"
}
]
}
Layouts
Layouts organize controls and other layouts into a visual structure.
VerticalLayout
Arranges elements vertically, one below the other.
{
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/firstName" },
{ "type": "Control", "scope": "#/properties/lastName" }
]
}
HorizontalLayout
Arranges elements horizontally, side by side.
{
"type": "HorizontalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/firstName" },
{ "type": "Control", "scope": "#/properties/lastName" }
]
}
Group
Groups related controls together with an optional label.
{
"type": "Group",
"label": "Personal Information",
"elements": [
{ "type": "Control", "scope": "#/properties/firstName" },
{ "type": "Control", "scope": "#/properties/lastName" }
]
}
Categorization
Organizes content into tabs or wizard-style steps. A Categorization contains multiple Category elements, each representing a step in the form.
{
"type": "Categorization",
"elements": [
{
"type": "Category",
"label": "Personal Info",
"elements": [
{ "type": "Control", "scope": "#/properties/personalInfo/properties/firstName" },
{ "type": "Control", "scope": "#/properties/personalInfo/properties/lastName" }
]
},
{
"type": "Category",
"label": "Contact Info",
"elements": [
{ "type": "Control", "scope": "#/properties/contactInfo/properties/email" },
{ "type": "Control", "scope": "#/properties/contactInfo/properties/phone" }
]
}
]
}
Categories correspond to steps in the schema. Each Category typically maps to a root-level schema property, enabling progressive disclosure as users complete each step.
ListWithDetail
Renders an array as a master-detail view — a list of items on one side and a detail form for the selected item.
{
"type": "ListWithDetail",
"scope": "#/properties/addresses",
"options": {
"detail": {
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/street" },
{ "type": "Control", "scope": "#/properties/city" }
]
}
}
}
Controls
Controls render input fields and bind them to schema properties.
Control
The Control element renders an input based on the schema type at the specified scope.
{
"type": "Control",
"scope": "#/properties/email",
"label": "Email Address"
}
| Property | Description |
|---|
scope | JSON Pointer to the schema property (e.g., #/properties/email) |
label | Display label for the control (optional — derived from schema if omitted) |
options | Custom options to modify control behavior |
The renderer automatically selects the appropriate input type based on the schema:
| Schema Type | Rendered As |
|---|
string | Text input |
string + format: "date" | Date picker |
string + enum | Dropdown/select |
number | Number input |
boolean | Checkbox or toggle |
array | List with add/remove |
Rules
Rules control the visibility and enabled state of elements based on data conditions.
{
"type": "Control",
"scope": "#/properties/employerName",
"rule": {
"effect": "SHOW",
"condition": {
"scope": "#/properties/employmentStatus",
"schema": { "const": "employed" }
}
}
}
Effects
| Effect | Description |
|---|
SHOW | Show the element when condition is true, hide otherwise |
HIDE | Hide the element when condition is true, show otherwise |
ENABLE | Enable the element when condition is true, disable otherwise |
DISABLE | Disable the element when condition is true, enable otherwise |
Conditions
A condition specifies a scope (the property to evaluate) and a schema that the value must match.
{
"condition": {
"scope": "#/properties/country",
"schema": { "enum": ["US", "CA"] }
}
}
Common condition patterns:
| Pattern | Schema |
|---|
| Equals a value | { "const": "value" } |
| One of many values | { "enum": ["a", "b", "c"] } |
| Not empty | { "minLength": 1 } |
Options
The options property on controls allows you to customize behavior. These are standard JSON Forms options.
Array options
Options for array controls:
| Option | Description |
|---|
showSortButtons | Shows buttons to reorder items |
elementLabelProp | Property to use as the label for each item in a list |
disableAdd | Prevents adding new items (renderer-specific) |
disableRemove | Prevents removing items (renderer-specific) |
{
"type": "Control",
"scope": "#/properties/documents",
"options": {
"elementLabelProp": "name",
"showSortButtons": true
}
}
readonly
Renders the control as read-only.
{
"type": "Control",
"scope": "#/properties/accountId",
"options": {
"readonly": true
}
}
detail
For ListWithDetail layouts, specifies the UI Schema for the detail view.
{
"type": "ListWithDetail",
"scope": "#/properties/items",
"options": {
"detail": {
"type": "VerticalLayout",
"elements": [...]
}
}
}
Custom options
The Enterprise API Suite extends JSON Forms with custom options for specific use cases.
dataSource
Specifies a data source for populating select options dynamically. You can optionally filter values using exclude.
{
"type": "Control",
"scope": "#/properties/country",
"options": {
"dataSource": "countries",
"exclude": {
"restrictions": [
{
"scope": "citizenship"
}
]
}
}
}
| Property | Description |
|---|
dataSource | The data source to fetch options from (e.g., "countries") |
exclude.restrictions | Array of restrictions to filter values from the data source |
exclude.restrictions[].scope | The restriction scope (e.g., citizenship, residence, geolocation, phone) |
Next steps