- 27 Feb 2025
-
DarkLight
-
PDF
Using Dynamic Dependency in JSON Forms
- Updated on 27 Feb 2025
-
DarkLight
-
PDF
The following examples demonstrate how field dependencies can improve the dynamism and adaptability of your JSON forms.
- The first populates a dropdown menu with all available Configuration Manager devices. Once a device is selected via this dropdown, its interfaces are made accessible via a second dropdown.
- The second limits the number of forms returned by a search based on the value of a number input.
See JSON Forms for details on creating JSON Forms and working with Form Builder to create the form elements referenced throughout this guide.
Example 1 — Retrieving Device Interfaces (GET Request)
Follow these steps to build and configure dynamic dependencies in the JSON form. As the form is built, it can be previewed and the generated form schemas can be inspected.
Step 1: Build JSON Form Structure
First, create the structure of the JSON form:
-
Create a JSON Form using the Automation Studio application.
-
Add two dropdown elements to the JSON form canvas using the Form Elements bin.
-
Hover over the menu button (…) at the far-right of each dropdown element and click the grid icon that appears. The Configure dialog opens.
-
Use the Label field to name the first dropdown element "Device" and the second "Interface" (Figure 1).
Figure 1
-
Click Save () to retain the naming inputs.
Step 2: Add Dynamic Data Binding to the Device Dropdown
Next, add the logic that is required to dynamically populate the fields. This is done via API calls.
-
Hover over the menu button (…) and click the gear icon (⚙) to open the Configure dialog.
-
Click the +Options button located at the bottom of the dialog and select the Dynamic configuration type. The Dynamic Data Binding editor displays.
-
For the Request Configuration, use the following parameters:
Method: POST Base URL: /configuration_manager API Route: /devices
-
In the Request Body editor, add options to help sort the list as well as limit the amount of data that is pulled. At a minimum, the suggested options are:
{ "options": { "limit": 10000, "start": 0, "sort": [ { "name": 1, "address": -1, "port": 1 } ] } }
-
Once the Request Body is added, click the Make API Call button to generate the Response Body (Figure 2).
Figure 2
-
For Data Mapping, use
Source-To-Target
and the field inputs below.Source Property: /list Property Key: /name
-
Click the Query Data button. The Data Mapping properties will generate a preview list of devices that are available and discoverable by Configuration Manager (Figure 3).
Figure 3
-
Click the Back button once all configurations are set and then click Save to retain all changes.
Step 3: Configure the Interface Dropdown's Field Dependencies
Once the "Device" selections are set, you can then configure the dynamic options for "Interfaces".
-
For the Request Configuration, use the following:
Method: GET Base URL: /configuration_manager API Route: /devices/:name/configuration
-
Populate the Define Parameters name field with an active device name found within Configuration Manager.
-
Click the Make API Call button to return the device configuration (Response Body).
-
For Data Mapping, select
JSON Transformation
and input the "Transform Device Config" JST file provided at the end of this guide. -
Click the Run Transformation button. The Target Data Preview editor displays the interface name.
-
For the Variables (Field Dependency), select
Form Reference
and input the Device field configured in the previous section./device
Figure 4
-
Click the Back button once all interface mappings are set and then click Save to retain all configuration changes.
Step 4: Validate the JSON Form
To test the logic of the JSON form:
- Navigate to Itential Platform → Automation Studio → JSON Forms. JSON Forms is listed in the left navbar as its own subcategory in Automation Studio.
- Expand the JSON Forms menu in the left navbar and select the JSON Form.
- Click the eye icon at the top to open the Preview Form dialog.
- Select a device from the Device dropdown. Likewise, select the interface captured from the device configuration in the Interface dropdown.
- Click Show Form Data to display the JSON schema. Click Close to return to the preview modal.
Figure 5
The information presented within Preview Form is from a live device and may take a few seconds to display based on the size of the device configuration as well as network congestion.
JSON Transformation File for Device Config
To import, copy the JSON into a .txt
file and save it as “Transform Device Config.jst.json”. Then import the file into your transformation library under Automation Studio.
{
"name": "Transform Device Config",
"incoming": [
{
"$id": "config",
"type": "string"
}
],
"outgoing": [
{
"$id": "out",
"type": "array"
}
],
"steps": [
{
"id": 2,
"type": "assign",
"from": {
"location": "incoming",
"name": "config",
"ptr": ""
},
"to": {
"location": "method",
"name": 1,
"ptr": "/args/0/value"
},
"context": "#"
},
{
"id": 1,
"type": "method",
"library": "String",
"method": "split",
"args": [
null,
"\n",
null
],
"view": {
"row": 1,
"col": 1
},
"context": "#"
},
{
"id": 4,
"type": "assign",
"from": {
"location": "method",
"name": 1,
"ptr": "/return"
},
"to": {
"location": "method",
"name": 3,
"ptr": "/args/0/value"
},
"context": "#"
},
{
"id": 3,
"type": "method",
"library": "Array",
"method": "filter",
"args": [
null,
"ƒ_query_1"
],
"view": {
"row": 2,
"col": 2
},
"context": "#"
},
{
"id": 6,
"type": "method",
"library": "Array",
"method": "map",
"args": [
null,
"ƒ_map_1"
],
"view": {
"row": 1,
"col": 3
},
"context": "#"
},
{
"id": 7,
"type": "assign",
"from": {
"location": "method",
"name": 3,
"ptr": "/return"
},
"to": {
"location": "method",
"name": 6,
"ptr": "/args/0/value"
},
"context": "#"
},
{
"id": 8,
"type": "assign",
"from": {
"location": "method",
"name": 6,
"ptr": "/return"
},
"to": {
"location": "outgoing",
"name": "out",
"ptr": ""
},
"context": "#"
}
],
"functions": [
{
"name": "ƒ_query_1",
"incoming": [
{
"type": [
"array",
"boolean",
"number",
"integer",
"string",
"object",
"null"
],
"$id": "element"
},
{
"title": "index",
"type": "number",
"optional": true,
"$id": "index"
},
{
"type": "array",
"$id": "array",
"optional": true
},
{
"$id": "thisArg",
"type": "object",
"properties": {},
"isContext": true,
"isThis": true,
"isIndexed": true
}
],
"outgoing": [
{
"title": "return",
"type": "boolean",
"$id": "return"
}
],
"steps": [
{
"id": 5,
"type": "assign",
"from": {
"location": "incoming",
"name": "element",
"ptr": ""
},
"to": {
"location": "method",
"name": 4,
"ptr": "/args/0/value"
},
"context": "#"
},
{
"id": 4,
"type": "method",
"library": "String",
"method": "trim",
"args": [
null
],
"view": {
"row": 2,
"col": 1
},
"context": "#"
},
{
"id": 6,
"type": "assign",
"from": {
"location": "method",
"name": 4,
"ptr": "/return"
},
"to": {
"location": "method",
"name": 1,
"ptr": "/args/0/value"
},
"context": "#"
},
{
"id": 1,
"type": "method",
"library": "String",
"method": "startsWith",
"args": [
null,
"interface",
null
],
"view": {
"row": 1,
"col": 1
},
"context": "#"
},
{
"id": 3,
"type": "assign",
"from": {
"location": "method",
"name": 1,
"ptr": "/return"
},
"to": {
"location": "outgoing",
"name": "return",
"ptr": ""
},
"context": "#"
}
],
"functions": [],
"view": {
"col": 1,
"row": 3
},
"id": "ƒ_query_1",
"comments": []
},
{
"name": "ƒ_map_1",
"incoming": [
{
"type": [
"array",
"boolean",
"number",
"integer",
"string",
"object",
"null"
],
"$id": "currentValue"
},
{
"title": "index",
"type": "number",
"optional": true,
"$id": "index"
},
{
"type": "array",
"$id": "array",
"optional": true
},
{
"$id": "thisArg",
"type": "object",
"properties": {},
"isContext": true,
"isThis": true,
"isIndexed": true
}
],
"outgoing": [
{
"title": "newValue",
"type": [
"array",
"boolean",
"number",
"integer",
"string",
"object",
"null"
],
"editable": true,
"$id": "newValue"
}
],
"steps": [
{
"id": 1,
"type": "method",
"library": "String",
"method": "trim",
"args": [
null
],
"view": {
"row": 1,
"col": 1
},
"context": "#"
},
{
"id": 2,
"type": "assign",
"from": {
"location": "incoming",
"name": "currentValue",
"ptr": ""
},
"to": {
"location": "method",
"name": 1,
"ptr": "/args/0/value"
},
"context": "#"
},
{
"id": 3,
"type": "assign",
"from": {
"location": "method",
"name": 1,
"ptr": "/return"
},
"to": {
"location": "outgoing",
"name": "newValue",
"ptr": ""
},
"context": "#"
}
],
"functions": [],
"view": {
"col": 1,
"row": 3
},
"id": "ƒ_map_1",
"comments": []
}
],
"view": {
"col": 3,
"row": 5
},
"_id": "6472c5cb363dd75d098b8d0d",
"description": "",
"comments": [],
"version": "3.23.3-2022.1.14"
}
Example 2 — Limiting a Form Search (POST Request)
In this example, a dynamic dropdown named Forms makes a POST request to Itential Platform's /formbuilder/forms/search
endpoint. This populates the dropdown with a list of forms that meet the criteria specified in the request body (for more information, see Itential's API documentation). One property of the request body, /options/maxResults
, is responsible for limiting the number of forms returned by the request. In practical terms, this means it also limits how many forms are displayed by the dropdown.
We would like to allow the form operator to dictate this limit; as such, we will also create a number input named Form Limit. In our dropdown configuration, we will turn /options/maxResults
into a field dependency, sourcing its value from the Form Limit input.
Field dependencies were made compatible with POST requests in the Platform 6 version of Itential Platform. In prior versions, they could only be used with GET requests.
Step 1: Build JSON Form Structure
First, we must create a skeleton form. We'll build it out in the later steps. To begin:
- Drag and drop a number input and a dropdown onto a fresh JSON form. As elements are placed, the form will begin to resemble a table, with each element comprising a separate row.
- Hover over the more options (horizontal ellipsis) icon at the end of the number input's row. A gear icon will display; click it to open the Configure modal.
- Edit the number input's Label to read "Form Limit." Then, click the Save button located at the bottom of the modal.
- Open the dropdown's Configure modal and edit its Label to read "Forms."
Do not close the dropdown's Configure modal; we will be making further configuration changes in the next section.
Figure 6: Skeleton Form
Step 2: Add Dynamic Data Binding to the Forms Dropdown
Next, we must set up dynamic data binding for the Forms dropdown.
-
Click the + Options button at the bottom-right corner of the modal. The Configure: Options modal will appear.
-
Under the Type header, click the Dynamic radio button. The dropdown's Dynamic Data Binding options will display.
-
Set the Request Configuration as follows:
Method: POST Base URL: /formbuilder API Route: /forms/search
-
Set the Request Body as follows:
{ "options": { "maxResults": 25, "startAt": 0, "sort": { "name": 1 }, "fields": [ "name", "children", "elements", "createdBy", "created", "lastUpdatedBy", "lastUpdated", "tags" ], "filter": { "name": { "$regex": "(e)", "$options": "i" } }, "expand": [ "createdBy", "lastUpdatedBy" ] } }
-
Click the Make API Call button to populate the Response Body. In this scenario, you should see a list of forms.
Figure 7: Dynamic Data Binding
-
Under the Data Mapping header, click the Source-To-Target option.
-
Examine the response body. Note that every top-level object in the
results
array contains aname
key corresponding to a different form. We would like to display these keys in the dropdown. To do so, set the Source Property and the Property Key fields as follows:Source Property: /results Property Key: /name
-
Click the Query Data button. A preview of the data that will be displayed by the dropdown appears; in this scenario, you should see a list of form names.
Figure 8: Data Mapping Settings
-
Under the Variables (Field Dependency) header, click the + Variable button. Two fields will appear: the Request Body Pointer and the Schema Reference.
-
We would like to parameterize the request body's
/options/maxResults
property, replacing its value with that of the Form Limit number input. To do so, configure the fields as follows:Request Body Pointer: /options/maxResults Schema Reference: /formLimit
-
When you are finished, click the Back button to return to the Configure modal. Then, click the Save button to save your changes and exit the modal.
Figure 9: Field Dependency Settings
Step 3: Test Form Behavior
All that's left is to confirm that the form is functioning as intended:
- Click the Preview JSON Form (eye icon) button located near the upper-right corner of the form builder. A functional preview of your form will be displayed.
- Confirm that the Form Limit number input effectively caps the Forms dropdown's options.
Working with API Calls in JSON Forms with Dynamic Data Binding
When working with Dynamic Data Binding in JSON Forms, it is important to know the adapter calls do not always translate directly to the system-level API call the adapter is translating. This mainly applies to system-level GET
calls.
GET/POST API Calls
As a criterion, all system-level GET
calls with defined query parameters (optional or mandatory) in the adapter's OpenAPI/Swagger specification document will be treated (translated) as adapter POST
calls.
To illustrate, let's refer to the F5 BIG-IP API depicted in the figure below.
Figure 10: Retrieve BIG-IP Devices
At the system-level, this is a GET
API call. However, in order to make it an adapter call, the API has to be a POST
request that requires an object with the object keys listed. Without those parameters in the request body, the adapter call will not work nor provide any output. In this instance, the object keys can be provided as empty values:
{ "select":"", "filter":""}
Use OpenAPI Help to Access Parameters
For all system-level GET
calls that need to be translated to POST
calls, the required parameters that need to be provided can be found through:
https://IAP_IP-LINK_Address:PORT/rest-api
If an adapter GET
call is not listed, two items need to be reviewed:
-
Validate that an adapter
POST
call associated with the system does not exist. -
Validate the developer building the JSON form has authorization to make the adapter call that is being attempted.
Related Reading