Skip to main content

Dynamic Forms V1 and V2

TODO

This page has multiple screenshots in the original Notion source (component titles, placeholders, etc.). Screenshots pending migration from Notion — see the Notion source for reference in the meantime.

Overview

  • This document outlines the structure and configuration of the various form components used in the SDK.
  • It is a reference for developers, designers, and stakeholders to understand how these components function and interact.
  • Each form component is defined with a specific schema detailing its required and optional properties.
  • The document covers the configs of all components in Dynamic Form V1 and Dynamic Form V2 (web components).
  • Validation rules, event handling (onClick, onChange, onValidated), and component behaviours are specified.

Purpose & use case

Who is this for? GTM teams, developers, support teams, SA/IEs, and anyone who wants to use the Dynamic Form module in their workflow config.

When should this be used? Whenever using Dynamic Form V1 and V2 (web components) in workflow config, or when adding components to a form V1/V2 module.

Dynamic Form V1

Core concepts

Structure of the module
  • properties

    • sectionsJSONArray [required] — array of sections.
      • idString [required] — unique id for the section.
      • componentsJSONArray [required] — array of all components to render for the form.
        • Event listeners (onClick, onValidated, etc. — optional)

          • reload — reload all default properties or reload only specific properties of any component within the same module.
            • <componentId> — id of the component to reload. Either list the properties to reload (e.g. visible, enabled) or pass {} to reload the whole component.

          Example:

          "onClick": {
          "reload": {
          "resendContainer": {
          "visible": "yes",
          "enabled": "no"
          },
          "resendTimer": {}
          }
          }
  • persistStateString, defaults to yes. When set to no, the SDK does not display values entered previously.

Default properties by component type (for partial reload):

title:         ['visible', 'text'],
description: ['visible', 'text'],
checkbox: ['visible', 'enabled', 'enable', 'required', 'text'],
date: ['visible', 'enabled', 'enable', 'required'],
dropDown: ['visible', 'required', 'enabled'],
file: ['visible', 'enabled', 'required'],
input: ['visible', 'enabled', 'required', 'value'],
hint: ['visible', 'text'],
textBlock: ['visible', 'text'],
visibleOnly: ['visible'], // loader, divider
container: ['visible', 'enabled'],
button: ['visible', 'enabled', 'loading', 'text'],
dateSpinner: ['visible', 'enable', 'required'],
image: ['visible', 'value'],
inputBlocks: ['visible', 'enabled', 'required'],
timer: ['visible', 'enabled'],
radio: ['visible', 'enabled', 'selected'],
chips: ['enabled', 'visible', 'selected'],
dynamicList: ['visible', 'data'],
Sample workflow module config
{
"type": "dynamicForm",
"subType": "form",
"id": "module_dynamicForm",
"nextStep": "",
"properties": {
"persistState": "no",
"sections": [
{
"id": "basicDetails",
"components": [
{
"id": "titleLabel",
"type": "label",
"subType": "title",
"text": "Enter basic details"
},
{
"id": "name",
"type": "text",
"subType": "singleLine",
"hint": "Enter name",
"title": "Name as per Govt. ID",
"enabled": "yes",
"visible": "yes",
"required": "yes",
"keyboard": "text",
"validation": [
{
"type": "regex",
"value": "^[a-zA-Z ]*$",
"errorMsg": "Please enter a valid name"
},
{
"type": "rule",
"value": "module_dynamicForm.name.value != ''",
"errorMsg": "Please enter a valid name"
}
],
"onValidated": {
"reload": {
"proceedButton1": {},
"proceedButton2": {
"enabled": "yes"
}
}
}
}
]
}
]
}
}
Frequently used component properties
tip

These properties may not be applicable to all components. Properties for individual components are discussed in the next section.

Enabled

  • enabled tells whether the component should be interactable by the user or read-only.
  • Optional property, defaults to yes.
  • Takes a static value (yes/no) or a rule that evaluates to yes/no.
  • Examples: enabled: yes or enabled: (id_card_validation.front.idNumber.confidence == 'low').

Visible

  • visible tells whether the component should be displayed.
  • Optional, defaults to yes.
  • Static (yes/no) or rule.
  • Examples: visible: yes or visible: (form.currentAddressSameAsPermanent.value == 'no').

Required

  • required tells whether the field is mandatory or optional.
  • Optional, defaults to yes.
  • Static (yes/no) or rule.
note

In Web SDK, required preliminarily decides the value of isValid property.

  • If required is yes, the isValid property of the same component is no initially. Later, based on validation added, isValid is set accordingly.
  • If required is no, isValid is set to yes.
  • Having required: yes does not automatically disable the next-step button until data is entered — the enable rule of the button has to be written based on required and isValid to achieve that.

Validation

  • validation is an array of rules that should be satisfied for the value of a field to be valid.
  • Optional. By default no validation is done.
  • Validation runs after user interacts with the field (typing then leaving, selecting from dropdown, etc.).
  • Two types: regex and rule.

Examples:

"validation": [{ "type": "regex", "value": "[\\w]+", "errorMsg": "" }]
"validation": [{ "type": "rule", "value": "(form.password.value == this.value)", "errorMsg": "" }]
"validation": [{ "type": "rule", "value": "(form.sameAddress.value == 'yes')", "errorMsg": "" }] // for checkboxes
"validation": [{ "type": "rule", "value": "(form.password.isValid == 'yes')", "errorMsg": "" }] // to check if field is not empty (required: yes) and validation passed

Value

  • The initial value of the field when rendered.
  • Can be empty string, a fixed string, a variable, or for dropdowns a value from the items array. For checkboxes, yes/no.
  • Optional. Defaults: "" for most, no (unchecked) for checkboxes.

Technical details & workflows — component schemas

label
{
"id": "descLabel",
"type": "label",
"subType": "title",
"text": "This is sample text",
"visible": "yes"
}

Required:

  • id (String), type must be "label".
  • subType — one of "title", "subTitle", "textBlock", "hint".
  • text (String, can be empty).

Optional: visible, width, height (Fill/Wrap/numeric = pixels).

button
{
"id": "button_signature_capture",
"type": "button",
"subType": "primary",
"text": "Capture Cancelled Cheque",
"onClick": {
"nextStep": "module_cheque"
}
}

Required: id, type ("button"), text, subType (one of "primary", "secondary", "tertiary").

Optional: visible, enabled, width, height (Fill/Wrap/numeric).

Event handlers — onClick:

  • reload (object), reloadComponents (deprecated), nextStep (String).

Exposed property — value: not an input, but accessible in rules. yes once clicked, no by default.

text
{
"id": "addressLine1",
"type": "text",
"title": "House Number",
"required": "('yes' == 'yes')",
"keyboard": "text",
"value": "module_addressSplit.Line1",
"visible": "(module_common_show_address.perAddCorrect.value == 'N')",
"enabled": "(module_common_show_address.perAddCorrect.value == 'N')",
"validation": [
{
"type": "regex",
"value": "^(?=.*[a-zA-Z0-9])[a-zA-Z0-9,./ \\-]{1,120}$",
"errorMsg": "A number or letter is required. Only . , / - allowed. Limited to 120 characters"
}
],
"onValidated": {
"reload": { "proceedButton": {} }
}
}

Required: id, type ("text").

Optional: subType ("singleLine", "multiLine", "blocks"), title, hint, height/width, visible, value, enabled, required, keyboard ("text"/"number"/"email"/"phone").

Validation: array of { type: "regex" | "rule", value, errorMsg }.

Event handlers: onValidated, onChange — each with reload, deprecated reloadComponents, and nextStep.

date
{
"id": "grdian1dob",
"title": "Date Of Birth",
"hint": "Date Of Birth",
"type": "date",
"format": "dd-MM-yyyy",
"required": "yes",
"enabled": "yes",
"subType": "spinner",
"visible": "yes",
"dateRange": {
"startMonth": -1300,
"endMonth": -218,
"errorMsg": "Guardian must be atleast 18 years old"
},
"onValidated": {
"reloadComponents": { "button_id_jEbFxD": {} }
}
}

Required: id, type ("date").

Optional: subType ("spinner"/"default"), title, hint, dateRange ({startMonth, endMonth, errorMsg}), visible, format (combination of yyyy/YYYY/mm/MM/DD/dd), required, enabled, value, width/height, content (e.g., {{2}}-{{2}}-{{4}}).

Validation + event handlers: same as text.

dropdown
{
"id": "dropdown_id1",
"title": "Relationship with the Account Holder",
"hint": "Relationship with the Account Holder",
"type": "dropdown",
"items": ["defaultOption", "spouse", "son", "daughter"],
"labels": {
"defaultOption": "Select Option",
"spouse": "Spouse",
"son": "Son",
"daughter": "Daughter"
},
"value": "defaultOption",
"required": "lib_module.checkbox.value == 'yes'"
}

Required: id, type ("dropdown"), items (array), labels (object).

Optional: subType ("dropdown"), title, hint, value, visible, required, enabled, width/height.

Validation + event handlers: same pattern (onValidated, onChange).

checkbox
{
"id": "PEP",
"type": "checkbox",
"text": "I am not a Politically Exposed person (PEP)",
"required": "yes",
"value": "yes",
"onChange": { "reload": { "proceedButton": {} } }
}

Required: id, type ("checkbox"), text.

Optional: subType ("checkbox"), value ("yes"/"no"), required, visible, enabled, width/height.

Event handlers: onChange, onValidated.

file
{
"id": "statement",
"type": "file",
"subType": "file",
"version": "2",
"title": "Attach Proof",
"subTitle": "Overall size of files cannot be more than 5MB",
"helperTextIdle": "You can attach PDF, PNG or JPEGs",
"errorTextFile": "Error in files attached. Please attach them again",
"errorTextSizeMax": "Maximum allowed file size is 5MB",
"visible": "yes",
"enabled": "yes",
"required": "yes",
"maxFileSize": 5000,
"pickerTitle": "What file type are you attaching?",
"allowMultipleTypes": "no",
"supportedFiles": [
{ "type": "documents", "title": "PDF Document", "extensions": ["pdf"] },
{ "type": "images", "title": "Pictures or Images", "extensions": ["jpg", "jpeg", "png"] }
]
}

Required: id, type ("file"), subType ("file").

Optional: title, subTitle, errorTextFile, helperTextIdle, helperTextActive, errorTextSizeMax, pickerTitle, visible, maxFileSize, supportedFiles (array of { type: "documents" | "images" | "videos", title, extensions }), required, enabled, validation, onValidated, onChange, version ("1" or "2").

vertical and horizontal containers
{
"id": "step2Card",
"type": "vertical",
"subComponents": [
{ "id": "step2CardLabel", "type": "label", "subType": "title", "text": "Step 2: Read out the statements" }
]
}

Required: id, type ("vertical" or "horizontal").

Optional: subType (matching type), visible, enabled, width/height, text (for horizontal only), nextStep (horizontal only).

Event handlers: onClick with reload, reloadComponents, nextStep.

Nested components: subComponents (array).

radio
{
"id": "panRadio",
"type": "radio",
"enabled": "yes",
"value": "no",
"text": "PAN",
"onClick": {
"reload": {
"aadhaarRadio": { "value": "no" },
"aadhaarNumber": { "visible": "no" },
"PANNumber": { "visible": "yes" }
}
}
}

Required: id, type ("radio").

Optional: subType ("default"), enabled, visible, text, value, selected ("yes"/"no").

Event handlers: onClick.

chip
{
"id": "chip2",
"type": "chip",
"subType": "default",
"enabled": "yes",
"visible": "module_dynamicForm_17.dropDownCheckbox.value == 'no'",
"required": "yes",
"text": "Chip 2",
"value": "a"
}

Required: id, type ("chip"), subType ("default").

Optional: enabled, visible, text, value, selected ("yes"/"no").

Icons: leadingIcon, trailingIcon — each with imageUrl, selectedImageUrl, disabledImageUrl.

Event handlers: onClick.

list
{
"id": "cardSelectionGroup",
"type": "list",
"subType": "grid",
"numberOfColumns": "2",
"selectionMode": "single",
"value": { "text": "Aadhaar", "val": "aadhaar" },
"data": [
{ "text": "Aadhaar", "val": "aadhaar" },
{ "text": "PAN", "val": "pan" },
{ "text": "DL", "val": "dl" }
],
"itemsGenerator": {
"id": "cell",
"type": "horizontal",
"onClick": { "reload": { "cardSelectionGroup": {} } },
"subComponents": [
{
"id": "radio_button",
"type": "radio",
"subType": "default",
"value": "$item.val",
"text": "$item.text",
"selected": "$item.val == cardSelectionGroup.value.val"
}
]
}
}

Required: id, type ("list"), data, itemsGenerator.

Optional: subType ("vertical"/"grid"/"staggered"), selectionMode ("single"), numberOfColumns (required if subType is "grid"), visible, value.

divider
{ "id": "orLabel1", "type": "divider", "subType": "optional", "text": "OR" }

Required: id, type ("divider").

Optional: subType ("optional"), visible, text.

timer
{
"id": "messageTimer",
"type": "timer",
"subType": "countdown",
"enabled": "yes",
"visible": "no",
"duration": "5",
"onComplete": {
"reload": { "errorMessageContainer": { "visible": "no" } }
}
}

Required: id, type ("timer"), subType ("timer" or "countdown"), duration.

Optional: text, visible, enable.

Event handlers: onComplete.

loader
{ "id": "emailVerifyOtpLoader", "type": "loader", "subType": "loader", "visible": "no" }

Required: id, type ("loader"), subType ("loader").

Optional: visible, height, width.

image
{
"id": "arrowIcon2",
"type": "image",
"height": "10",
"value": "https://upskilling-sample-upload-2.s3.ap-south-1.amazonaws.com/arrorHigh.png"
}

Required: id, type ("image"), value (image URL).

Optional: subType ("image"), visible, height, width, onClick.

Dynamic Form V2 — Web Components

Why Dynamic Form V2?
  1. Customisation limitations — while Dynamic Form V1 supports multiple components, its customisation options are limited. V2 allows full customisation, enabling users to build components as needed.
  2. Component flexibility — V1 comes with a fixed set of components, restricting scalability. V2 removes this limitation, allowing users to create any component with any style and functionality.
  3. Unlimited possibilities — V2 is not bound by predefined structures, offering limitless potential for customisation and adaptability.

Core concepts

Structure of the module
  • stylesString — holds all the styles for corresponding components in stringified format.
  • scriptsJSONArray — external scripts needed to perform the desired action in the module.
  • stylesheetsJSONArray — external stylesheets needed for the component.
  • contentString [required] — holds HTML structure of the components; rendered as components on the screen.
  • componentConfigsJSONObject — holds the configs of individual components inside the module.
"<dom-id>": {
"sdkController": {
"visible": "<some-value>"
},
"dynamicHandlers": {
"children": ["<moduleId-of-child-modules>"],
"handlers": [
// same structure of reload obj here
]
},
"properties": {
"prop1": "<some-value>",
"prop2": "<some-value>"
},
"attributes": {
"disabled": "false",
"attr2": "<some-value>"
},
"events": {
"bl-input-change": {
"refresh": {
"attributes": ["atr1", "atr2"],
"properties": ["prop1", "prop2"]
},
"nextStep": "approve",
"reloadV2": {
"domId": {
"attributes": {},
"properties": { "prop": "value" }
}
}
}
}
}
Sample workflow module config
{
"type": "dynamicFormV2",
"subType": "formV2",
"id": "module_duKK2E_formV2",
"previousStep": "module_8tWz2Z_idcard_validation",
"nextStep": "",
"next_node_type": {
"hv_form_v2_5NedF6.events.retake-button-click.nextStep": "goto"
},
"properties": {
"styles": "#hv_form_v2_CXLzfi { border-radius: 6px; border: 1px solid #0000001A; align-items: center; margin: 8% 0% 0% 0%; } ...",
"scripts": [
"https://kycdev-hyperverge-co.s3.ap-south-1.amazonaws.com/audit-portal/stg/workflow-builder/componentLibTesting/bav1.js"
],
"content": "<button id=\"hv_form_v2_vk0sjN\"></button><div id=\"hv_form_v2_GsgoKv\">...</div>",
"stylesheets": [],
"componentConfigs": {
"hv_form_v2_vk0sjN": {
"attributes": {},
"properties": {
"textContent": "Disable OCR",
"componentConfigs": "[object Object]"
},
"events": {
"click": { "nextStep": "EXIT_POINT" }
},
"styles": {},
"sdkController": { "visible": "no" }
},
"hv_form_v2_kQe83Y": {
"attributes": {
"text": "Submit",
"font-weight": "600",
"background-color": "#554EF1",
"text-color": "white",
"border-color": "#554EF1"
},
"sdkController": { "enabled": "true" },
"events": {
"button-click": {
"refresh": { "properties": ["finalimgsrc", null] },
"nextStep": "module_disable_PassbookOCR"
}
}
},
"hv_form_v2_5NedF6": {
"attributes": {
"text": "Retake Image",
"background-color": "white",
"text-color": "#554EF1",
"border-color": "#554EF1"
},
"events": {
"retake-button-click": {
"refresh": {},
"nextStep": "module_8tWz2Z_idcard_validation"
}
}
}
},
"allowClose": true
},
"name": "PassBook Disable OCR Review Screen",
"superModuleType": "bav_verificationV4",
"superModuleId": ""
}

Technical details & workflows

For how to create and use web components using the builder and how it works, refer to the internal web-components builder documentation linked from the Notion source.

Was this helpful?
Ask AI

Ask anything about the internal documentation

AI answers are based on internal documentation. Verify critical information.