Authoring an adaptive form using a JSON Schema as its form model requires basic understanding of JSON Schema. It is recommended to read through the following content before this article.
Adobe Experience Manager Forms supports creation of an adaptive form by using an existing JSON Schema as the form model. This JSON Schema represents the structure in which data is produced or consumed by the back-end system in your organization. The JSON Schema you use should be compliant with v4 specifications.
The key features of using a JSON Schema are:
A JSON Schema consists of simple and complex element types. The elements have attributes that add rules to the element. When these elements and attributes are dragged onto an adaptive form, they are automatically mapped to the corresponding adaptive form component.
This mapping of JSON elements with adaptive form components is as follows:
"birthDate": {
"type": "string",
"format": "date",
"pattern": "date{DD MMMM, YYYY}",
"aem:affKeyword": [
"DOB",
"Date of Birth"
],
"description": "Date of birth in DD MMMM, YYYY",
"aem:afProperties": {
"displayPictureClause": "date{DD MMMM, YYYY}",
"displayPatternType": "date{DD MMMM, YYYY}",
"validationPatternType": "date{DD MMMM, YYYY}",
"validatePictureClause": "date{DD MMMM, YYYY}",
"validatePictureClauseMessage": "Date must be in DD MMMM, YYYY format."
}
JSON element, properties, or attributes | Adaptive form component |
---|---|
String properties with enum and enumNames constraint. Syntax,
|
Drop down component:
|
String property with format constraint. For example, email, and date. Syntax,
|
|
|
Text field |
number property |
Numeric Field with sub type set to float |
integer property |
Numeric Field with sub type set to integer |
boolean property |
Switch |
object property |
Panel |
array property | Repeatable Panel with min and max equal to minItems and maxItems respectively. Only Homogenous arrays are supported. So the items constraint must be an object and not an array. |
Adaptive Form uses information available in JSON Schema to map each generated field. In particular:
title
property serves as label for the adaptive form components.description
property is set as long description for an adaptive form component.default
property serves as initial value of an adaptive form field.maxLength
property is set as maxlength
attribute of the text field component.minimum
, maximum
, exclusiveMinimum
, and exclusiveMaximum
properties are used for Numeric box component.DatePicker component
additional JSON Schema properties minDate
and maxDate
are provided…minItems
and maxItems
properties are used to restrict the number of items/fields that may be added or removed from a panel component.readOnly
property sets the readonly
attribute of an adaptive form component.required
property marks the adaptive form field as mandatory whereas in panel(where type is object), the final submitted JSON data has fields with empty value corresponding to that object.pattern
property is set as the validation pattern (regular expression) in adaptive form.Here’s an example of a JSON Schema.
{
"$schema": "https://json-schema.org/draft-04/schema#",
"definitions": {
"employee": {
"type": "object",
"properties": {
"userName": {
"type": "string"
},
"dateOfBirth": {
"type": "string",
"format": "date"
},
"email": {
"type": "string",
"format": "email"
},
"language": {
"type": "string"
},
"personalDetails": {
"$ref": "#/definitions/personalDetails"
},
"projectDetails": {
"$ref": "#/definitions/projectDetails"
}
},
"required": [
"userName",
"dateOfBirth",
"language"
]
},
"personalDetails": {
"type": "object",
"properties": {
"GeneralDetails": {
"$ref": "#/definitions/GeneralDetails"
},
"Family": {
"$ref": "#/definitions/Family"
},
"Income": {
"$ref": "#/definitions/Income"
}
}
},
"projectDetails": {
"type": "array",
"items": {
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
},
"projects": {
"$ref": "#/definitions/projects"
}
}
},
"minItems": 1,
"maxItems": 4
},
"projects": {
"type": "array",
"items": {
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
},
"projectsAdditional": {
"$ref": "#/definitions/projectsAdditional"
}
}
},
"minItems": 1,
"maxItems": 4
},
"projectsAdditional": {
"type": "array",
"items": {
"properties": {
"Additional_name": {
"type": "string"
},
"Additional_areacode": {
"type": "number"
}
}
},
"minItems": 1,
"maxItems": 4
},
"GeneralDetails": {
"type": "object",
"properties": {
"age": {
"type": "number"
},
"married": {
"type": "boolean"
},
"phone": {
"type": "number",
"aem:afProperties": {
"sling:resourceType": "/libs/fd/af/components/guidetelephone",
"guideNodeClass": "guideTelephone"
}
},
"address": {
"type": "string"
}
}
},
"Family": {
"type": "object",
"properties": {
"spouse": {
"$ref": "#/definitions/spouse"
},
"kids": {
"$ref": "#/definitions/kids"
}
}
},
"Income": {
"type": "object",
"properties": {
"monthly": {
"type": "number"
},
"yearly": {
"type": "number"
}
}
},
"spouse": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"Income": {
"$ref": "#/definitions/Income"
}
}
},
"kids": {
"type": "array",
"items": {
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
}
},
"minItems": 1,
"maxItems": 4
}
},
"type": "object",
"properties": {
"employee": {
"$ref": "#/definitions/employee"
}
}
}
Definition keys are used to identify reusable schemas. The reusable schema definitions are used to create fragments. It is similar to identifying complex types in XSD. A sample JSON Schema with definitions is given below:
{
"$schema": "https://json-schema.org/draft-04/schema#",
"definitions": {
"address": {
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
}
},
"type": "object",
"properties": {
"billing_address": { "$ref": "#/definitions/address" },
"shipping_address": { "$ref": "#/definitions/address" }
}
}
The above example defines a customer record, where each customer has both a shipping and a billing address. Structure of both the addresses is same—addresses have a street address, city and state— so it is a good idea to not duplicate the addresses. It also makes addition and deletion of fields easy for any future changes.
You can use the aem:afProperties property to preconfigure JSON Schema field to map to a custom adaptive form component. An example is listed below:
{
"properties": {
"sizeInMB": {
"type": "integer",
"minimum": 16,
"maximum": 512,
"aem:afProperties" : {
"sling:resourceType" : "/apps/fd/af/components/guideTextBox",
"guideNodeClass" : "guideTextBox"
}
}
},
"required": [ "sizeInMB" ],
"additionalProperties": false
}
JavaScript is the expression language of adaptive forms. All the expressions are valid JavaScript expressions and use adaptive forms scripting model APIs. You can pre-configure form objects to evaluate an expression on a form event.
Use the aem:afproperties property to preconfigure adaptive form expressions or scripts for adaptive form components. For example, when the initialize event is triggered, the below code sets value of telephone field and prints a value to the log :
"telephone": {
"type": "string",
"pattern": "/\\d{10}/",
"aem:affKeyword": ["phone", "telephone","mobile phone", "work phone", "home phone", "telephone number", "telephone no", "phone number"],
"description": "Telephone Number",
"aem:afProperties" : {
"sling:resourceType" : "fd/af/components/guidetelephone",
"guideNodeClass" : "guideTelephone",
"events": {
"Initialize" : "this.value = \"1234567890\"; console.log(\"ef:gh\") "
}
}
}
You should be a member of the forms-power-user group to configure scripts or expressions for form object. The below table lists all the script events supported for an adaptive form component.
Component \ Event | initialize |
Calculate | Visibility | Validate | Enabled | Value Commit | Click | Options |
---|---|---|---|---|---|---|---|---|
Text Field | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Numeric Field | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Numeric Stepper | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Radio Button | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Telephone | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Switch | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Button | ![]() |
![]() |
![]() |
![]() |
||||
Check Box | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|
Drop-down | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|
Image Choice | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|
Date Input Field | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
Date Picker | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|||
File Attachment | ![]() |
![]() |
![]() |
![]() |
![]() |
|||
Image | ![]() |
![]() |
||||||
Draw | ![]() |
![]() |
||||||
Panel | ![]() |
![]() |
Some examples of using events in a JSON are hiding a field on initialize event and configure value of another field on value commit event. For detailed information about creating expressions for the script events, see Adaptive Form Expressions.
Here is the sample JSON code for previously mentioned examples.
"name": {
"type": "string",
"aem:afProperties": {
"events" : {
"Initialize" : "this.visible = false;"
}
}
}
"Income": {
"type": "object",
"properties": {
"monthly": {
"type": "number",
"aem:afProperties": {
"events" : {
"Value Commit" : "IncomeYearly.value = this.value * 12;"
}
}
},
"yearly": {
"type": "number",
"aem:afProperties": {
"name": "IncomeYearly"
}
}
}
}
You can add the following restrictions to JSON Schema elements to limit the values acceptable to an adaptive form component:
Schema property |
Data Type |
Description |
Component |
|
String |
Specifies the upper bound for numeric values and dates. By default, the maximum value is included. |
|
|
String |
Specifies the lower bound for numeric values and dates. By default, the minimum value is included. |
|
|
Boolean |
If true, the numeric value or date specified in the component of the form must be less than the numeric value or date specified for the maximum property. If false, the numeric value or date specified in the component of the form must be less than or equal to the numeric value or date specified for the maximum property. |
|
|
Boolean |
If true, the numeric value or date specified in the component of the form must be greater than the numeric value or date specified for the minimum property. If false, the numeric value or date specified in the component of the form must be greater than or equal to the numeric value or date specified for the minimum property. |
|
|
String |
Specifies the minimum number of characters allowed in a component. The minimum length must be equal to or greater than zero. |
|
maxLength |
String | Specifies the maximum number of characters allowed in a component. The maximum length must be equal to or greater than zero. |
|
|
String |
Specifies the sequence of the characters. A component accepts the characters if the characters conform to specified pattern. The pattern property maps to the validation pattern of the corresponding adaptive form component. |
|
maxItems |
String | Specifies the maximum number of items in an array. The maximum items must be equal to or greater than zero. | |
minItems |
String | Specifies the minimum number of items in an array. The minimum items must be equal to or greater than zero. |
Adaptive forms do not support the following JSON Schema constructs:
Why I am not able to drag individual elements of a subform (structure generated from any complex type) for repeatable subforms (minOccours or maxOccurs values are greater than 1)?
In a repeatable subform, you must use the complete subform. If you want only selective fields, use the entire structure and delete the unwanted ones.
I have a long complex structure in Content Finder. How can I find a specific element?
You have two options:
What should be the extension of the JSON schema file?
The extension of JSON Schema file must be .schema.json. For example, <filename>.schema.json.