Advanced Form

The advanced form was introduced to provide more flexibility when building compilations used to capture user input. It is based on the react-jsonschema-form library.

The advanced form offers many features that are not explained in detail here but are described on the library documentation pages. The live playground is also a very useful resource to interactively experiment with the various form options. Additionally, also have a look at the JSON Schema online documentation.

Model

{
    "type": "advancedform",
    "data": {},       // form field data object
    "schema": {},     // Define the structure of the form data
    "uischema": {},   // Define which input control to use when editing a field
    "formOptions": {} // Define field specific actions and styling
}

Data

Refer to the generic widget page for a description of the general principles governing the treatment of data retrieved from a dataSource

The advanced form data element is an object with structure that matches the schema definition. It can be a flat set of key-value pairs but may also contain nested complex elements. For example:

{
    "house_address": {
        "street": "7 Church Street",
        "city": "Digby"
    },
    "firstName": "Joe",
    "lastName": "Bloggs",
    "age": 27,
    "telephone": "555 123 456"
}

Schema

The schema element serves to define the structure of the form data.

{
    "type": "object",
    "definitions": {},
    "dependencies": {},
    "description": "Form description",
    "title": "Form tile",
    "required": [],
    "properties": {}
}
Field Description

definitions

The definitions property can be used to declare one or more named composite object types which are referenced when defining properties. This is particularly useful when multiple fields in the form have the same object structure. $ref is used to reference the declared definitions (See address field in the example below)

Note: If a particular object field only appears once in the form, the nested structure can be declared in situ by directly providing the object properties.

description

Optional description, shown after the title.

dependencies

Used to define inter-field dependencies.

properties

Contains the declarations for the named form fields. They are always nested in schema elements of type "object". Refer to the properties section below for more detail.

readOnly

Render all the fields in the form read-only. Individual fields can be be made readOnly by using the ui:readOnly property

required

List of required fields which must have a value before the form can be submitted. Required fields without appropriate values will be shown with a red border when a submit is attempted.

The entries in the list refer to fields at the current object level. If the form contains nested fields, such as street and city in the example above, and these are required, then the property must be included at the schema level where they are declared as shown in the example below.

title

Optional form title shown at the top of the form.

type

Defines the top level type of form data and needs to be of set to object

Properties

The properties element, inside the schema section, is used to declare named fields shown on the form and saved in the data. At the schema level it defines the root data properties, which may in turn be complex objects containing their own properties.

Each property needs a type and may be further qualified using a number of available attributes, some of which are highlighted in the table below:

Field Description

allOf, anyOf, oneOf

These properties allow different elements of a schema to be selected from an array of possibilities providing a means to dynamically control which fields ultimately appear in the data. When using oneOf or anyOf a specific field is typically configured to make the selection of the schema structure to activate and will be shown as a dropdown letting the user choose the fields to populate. The ui:widget for this field should therefor be set to something like "select" or "radio" in the uischema.

default

Optional default value to assign if none is provided.

definitions

The definitions property can be used to declare one or more named composite object "types". This is particularly useful when multiple fields in the form have the same object structure. $ref is used to reference the definitions from a property (See address field in the example below)

Note: If a particular object field only appears once in the form, the nested structure can be declared in situ by directly providing the object properties.

description

Optional field description, shown after the title.

dependencies

Used to define inter-field dependencies.

enum

Enumeration used to define selectable options for a field. Note: When using enum fields be sure to select the appropriate ui:widget in the uischema.

enumNames

Custom labels used to provide readable names for numeric enum fields.

items

Defines the type of elements in array fields. This can be a simple type such as string or number, etc or it can be a composite type containing other fields. (refer to the Nested and Array examples live playground for more detail)

properties

Named properties of the root or nested form elements of type "object".

Note that the fields appear on-screen in the same order as they do in the properties section. The order can be explicitly set in the uischema using the ui:order property.

Refer to the library documentation for more details.

title

The field title is optional. If it is not provided, the field name (key) is used as the title.

type

Defines the type of the enclosing element. The root element must be of type object since it contains all the form fields. Individual form fields can have any of the following types:

  • array: Used for lists of data. Needs to have an items property set to declare the type of the array elements. (also see uischema for matching input controls.)

  • boolean: True/False value. Will be rendered as a check-box by default.

  • integer: Whole numbers. The form will do type validation to check that the provided input is an integer number.

  • number: Any number including decimals. The form will do type validation to check that the provided input is a integer or real number.

  • null: "dummy" entry used to provide extra information to form users. Null fields don’t present an input field nor do they appear in the data.

  • object: Object with named fields. Fields are declared in the properties of the enclosing object. (see example below)

  • string: Generic text input. Note that date fields need to be declared as strings since they are stored in ISO 8601 strings format.

The field type can also be an array of two elements. One being the base type, the other "null" if the field in question is nullable. (For example “type”: ["integer", "null"]). Since a null cannot be entered, the field default would also need to be set to null.

uniqueItems

Apply this property to array type fields to ensure that a specific entry can only be selected once.

Schema Examples

Definition and reference

In this example a number of schema options are shown. Note the use of definitions to define the address object with two fields and its use in the house_address field by referring to it with a $ref path.

{
    "type": "object",
    "required": [
        "firstName",
        "lastName",
        "age"
    ],
    "definitions": {
        "address": {
            "type": "object",
            "properties": {
                "street": {
                    "type": "string",
                    "title": "Street"
                },
                "city": {
                    "type": "string",
                    "title": "City"
                }
            },
            "required": [
                "street",
                "city"
            ]
        }
    },
    "properties": {
        "firstName": {
            "type": "string",
            "title": "First name"
        },
        "lastName": {
            "type": "string",
            "title": "Last name"
        },
        "age": {
            "type": "number",
            "title": "Age",
            "minimum": 18,
            "maximum": 67
        },
        "birth_month": {
                "type": "integer",
                "title": "Month of Birth",
                "enum": [1,2,3,4,5,6,7,8,9,10,11,12],
                "enumNames": [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
                ]
        },
        "telephone": {
            "type": "string",
            "title": "Telephone",
            "minLength": 10
        },
        "house_address": {
            "type": "object",
            "title": "House Address",
            "$ref": "#/definitions/address"
        },
        "email": {
            "type": "string",
            "title": "Email",
            "format": "email"
        }
    }
}

Composite array values

In this schema, the input field, called tuples, is an array containing objects with a name and a value declared directly in the property, rather than using a definition and reference as in the example above:

{
    "type": "object",
    "properties": {
        "tuples": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "value": {
                        "type": "number",
                        "enum": [ 1, 2, 3, 4 ]
                    }
                }
            }
        }
    }
}

Refer to the uiSchema example to see how to set the input controls to use for each of the fields.

Schema validation properties

The following schema validation properties are provided in the schema section of the form. Also refer to the uischema for additional validation options.

Field Description

exclusiveMinimum, exclusiveMaximum

Validate number to be strictly larger than or less than the stated minimum or maximum

exclusiveMinimum < Field Value < exclusiveMaximum

format

Allows a set of pre-defined schema formats to be used to validate strings. The Advanced Form supports the standard JSON Schema formats and adds two extra custom formats as defined here

minimum, maximum

Enable validation on the allowed values of integer and number field

minimumField Valuemaximum

maxItems, minItems

Set limits on the number of elements allowed in an array field.

maxLength, minLength

Set limits on the allowed length of a string property

multipleOf

Constrain the numeric field value to be a multiple of the multipleOf property, for example:

{
    "type": "number",
    "multipleOf" : 10
}

pattern

Validation regular expression to applied to string fields. Patten validation is only done on fields which contain data. This implies that to enforce patterns which require the text to contain a minimum number of characters, the field must also be required.

UI Schema

The UI Schema is used to manage the appearance of the form fields and specify which controls to use to edit them. It is recommended that a ui:widget be assigned to all form fields to ensure the edit controls used adhere to the overall styling of the WebStudio compilation and the selected theme.

The uiSchema property contains elements for all form-fields requiring configuration to be applied, the model for which looks something like this:

{
    "ui:order" : [] // Optional array used to set the display order of the form fields
    "<field-name>": { // Entry for each field requiring ui-configuration
        "<ui:xxx>" : "value" // See table below for available options
        "<nested-field-name>": {
            // configuration detail for fields in nested objects.
        }
    }
}

The angle brackets in the above fragment are used to indicate placeholders for implementation specific content.

Field Description

classNames

String field containing the names of one or more style classes to assign to the field. Refer to formOptions.styleByClassName for more details.

ui:description

Alternative / override field description. This one takes precedence over the description in the schema

ui:disabled

Set to true to disable the field and prevent the content from being selected. This setting on the face of it does the same as ui:readOnly, the difference is that the latter still allows the content to be selected.

ui:enumDisabled

This array property can be used to disable one or more options from an enum list. For example:

{
    "schema" : {
        "enumField": {
            "type" : "string",
            "enum" : ["One", "Two", "Three"]
        }
    },
    "uiSchema" : {
        "enumField": {
           "ui:enumDisabled" : ["Two"]
        }
    }
}

ui:help

Display an additional help string after the field input control.

ui:options

This is a composite property with the following fields:

accept

sets the file types that can be selected for fields of type "file". The value assigned to the accept property should be a MIME type string. The option is only enforces if the field format is also set to "data-url"

For example:

{
    "type": "advancedform",
    "schema": {
        "type": "object",
        "properties": {
            "file": {
                "type": "string",
                "title": "File",
                "format": "data-url"
            }
        }
    },
    "uiSchema": {
        "file": {
            "ui:help": "Select a JSON file",
            "ui:options": {
                "inputType": "file",
                "accept": "application/json"
            }
        }
    },
    "layout": {
        "x": 0,
        "w": 31,
        "h": 11,
        "y": 32,
        "static": false
    }
}
the data of the selected file is loaded into the work model as an encoded data-url.

addable
orderable
removable

These options only apply to fields of type "array". In the form, new elements can be added to array type fields by default, using the provided "+" button. The control is hidden when the addable option is set to false.

Likewise, elements can be re-ordered and removed with the provided form controls. These can also be hidden by setting the relevant property to false.

inline

when set to true, radio buttons and check-boxes can be shown in-line rather than on separate lines. For example, using an array field to allow users to select multiple options, the following setting could be used:

{
    "schema": {
        "type": "object",
        "properties": {
            "hobbies": {
                "type": "array",
                "title": "Hobbies",
                "description": "Check all that apply",
                "items": {
                    "type": "string",
                    "enum": [ "sports", "camping", "travel", "reading", "making" ]
                },
                "uniqueItems": true
            }
        }
    },
    "uiSchema": {
        "hobbies": {
            "ui:widget": "checkboxes",
            "ui:options": {
                "inline": true
            }
        }
    }
}

inputType

Note: Not all the options from the underlying library have been fully integrated with WebStudio yet. These will be documented as they are introduced.

  • color: The input control used for the field is a color-picker. Colors selected from the input dialog are returned as hexadecimal RGB values. For example, the value for red is "#ff0000"

  • file: Allows a file name to be picked from the local file system. The field name will be the path to the selected file.

  • password: Causes the field text to be obscured. Don’t set the ui:widget property with this setting yet.

  • text: Treat the input as a regular text box.

label

Setting the label property to false will cause the field name to be hidden.

placeholder

Place-holder text shown in the input box to provide users with a hint of the expected content.

rows

Used with a "textarea" ui:widget type, sets the number of rows in the edit box.

ui:placeholder

This is the same as the placeholder in the options field.

ui:readOnly

When set to true, the field value cannot be edited but is still selectable and can be copied to the clipboard.

ui:title

Overrides the field title provided in the schema section

ui:widget

This property is used to select the specific widget to use as the input control for the field. Available options are:

  • checkbox: Shows a single checkbox, typically used with a boolean field.

  • checkboxes: Shows a set of check-boxes. Can be used with array properties where multiple selections are made from an enum as shown in the inline example above.

  • datepicker: Provides an input box with an icon to bring up a date-time picker dialog.

  • hidden: Hides the field in the form.

  • password: Obfuscates entered characters. The same outcome can be achieved by setting the inputType equal to password

  • radio: Shows a radio-button associated with boolean or single selectable enum value. In case of the latter one radio button is shown for each enumeration.

  • range: Shows a range slider. The minimum and maximum values for the slider are taken from the schema minimum and maximum settings.

  • select: Drop-down list. When this ui:widget is used with properties of type array, multiple items can be selected.

  • text: Text input box

  • textarea: Shows a multi-line text input field

  • updown: Input field restricting the values that can be entered to a number, either integer or decimal.

uiSchema examples

Nested Fields:

Referring to the "Definition and Reference" example above, the uiSchema to set the address input controls for the street to a text-box and the city to a regular input would look something like this.

{
    "house_address": {
        "street": {
            "ui:widget": "textarea"
        },
        "city": {
            "ui:widget": "text" // Not really needed since string fields use this widget by default
        }
    }
}

The outer object name used is that of the containing field "house_address", rather then the type "address"

Nested fields in an array:

When the fields are contained in an array as is the case for the second schema example and require specific ui:widget specs, an items element needs to be added to the specification as shown:

{
    "tuples": {
        "items": {
            "name": {
                "ui:widget": "text"
            },
            "value": {
                "ui:widget": "select"
            }
        }
    }
}

Form Option

The form options provide further customization features that are specific to WebStudio. The formOptions property has the following structure:

{
    "formOptions" : {
        "datePickerOptions": {
            "format": "DD-MM-YYYY",
            "convertRelativeDate": true,
            "timeIntervals": 30
        },
        "entryOptions": {
            "<field-name>" : {
                "actions": { },
                "convertRelativeDate": {
                    "type": "number"
                }
            }
        },
        "styleByClassName": {
            "<custom-class-name>" : { }
        }
    }
}
Field Description

datePickerOptions

The date picker options are used to customize the behavior of all date-time input fields in the form. These settings can also be set at individual field level. Refer to the entryOptions section below.

The properties defined here only effect field that have their ui:widget configured to use the "datepicker" in the uiSchema section

convertRelativeDate

This property determines how a date-time value entered in a form field appears in the message payload of actions such as onChange, onSubmit etc.

The setting does not affect how the field value is written to the data element in the work-model when the form is submitted. The form data always contains the un-converted value entered in the field.

Options are:

  • false : Relative dates, of the form "*-10m", are submitted in the message payload exactly as entered in the input field.

  • true : Relative dates are converted to an absolute ISO Date string.

It is also possible to have relative time expressions converted to an epoch number by setting convertRelativeDate.type to "number" as shown below.

{
    "convertRelativeDate": {
        "type": "number"
    }
}

format

The format property is used to affect how date-time values are displayed in the form field.

It does not change how the value is written to the data element or message payload.

timeIntervals

Set the resolution, in minutes, of time options shown in the date-time picker dialog. By default the time interval is set to 30 minutes which means that the dialog shows options on the hour and 30 minutes past the hour.

By setting timeIntervals to 10 for example, the dialog will provide time options at 10 minute intervals.

entryOptions

Custom setting can be applied on specific fields, by adding a property with the field-name as the key and object as value. Supported object properties are listed below:

action

The action property is used to react to changes to selected form fields. Available hooks at field level are: onBlur, onChange, onChanged and onFocus.

Fox example, say we wanted to perform some action when the firstName field gets the input focus.

{
    "formOptions" : {
        "entryOptions": {
            "firstName" : {
                "actions": {
                    "onFocus" : {
                        "type" : "notify"
                    }
                }
            }
        }
    }
}

Field level actions for nested entries can be declared by providing the dot-notation path. Consider a form with the following schema:

{
"schema": {
        "type": "object",
        "properties": {
            "nested": {
                "type": "object",
                "properties": {
                    "field1": {
                        "type": "string",
                        "title": "Field 1"
                    }
                }
            }
        }
    }
}

To define an action pipeline to trigger when field1 gets the input focus, the entryOptions would look like this:

{
    "formOptions": {
        "entryOptions": {
            "nested.field1": {
                "actions": {
                    "onFocus": {
                        "type": "notify"
                    }
                }
            }
        }
    }
}

convertRelativeDate

See convertRelativeDate above

format

Sets the date-time display format for this field

timeIntervals

Sets the time resolution of the date-time picker dialog for this field

styleByClassName

This property is used to add custom styling to form fields. Let’s say for some fields in the form we want to use a different font. The style can be declared as follows:

  • In the formsOptions.styleByClassName add a property for the custom class name, let’s call it customFontClass. Add the style options in the style body.

  • In the uischema, include a classNames property with all fields where we want the new style to be applied and set the value to customFontClass

{
    "schema": {
        "type": "object",
        "properties": {
            "monoTextField": {
                "type": "string"
            }
        }
    },
    "uiSchema": {
        "monoTextField": {
            "ui:widget": "textarea",
            "classNames": "customFontClass",
            "ui:title": "Mono-space Text Field"
        }
    },
    "formOptions": {
        "styleByClassName": {
            "customFontClass": {
                "fontFamily": "Monaco",
                "fontSize": "larger"
            }
        }
    }
}

showValidationErrors

Validation error can be shown directly as annotations in the form by setting this property to true, or suppressed entirely by setting it false

Options

Set widget options.

{
    "options": {
        "showRefreshButton": true,
        "showToolbar": false,
        "refreshInterval": 10
    }
}
name description

showRefreshButton

Set this to false to hide the refresh button. By default the refresh button is visible.

showToolbar

Use to hide the complete toolbar.

refreshInterval

Refresh with an interval in seconds.

Actions

The Advanced Form supports a number of action hooks in addition to the default lifecycle ones, most of which can be used at form and field level by defining entryOptions as described above. The exceptions are onSubmit and onValidationError, which are not triggered separately for each field.

The Advanced Form actions are:

  • onBlur : This event fires whenever a field loses input focus.

  • onChange : Triggers on every input change.

  • onChanged : The action only triggers if the content of the field, when it loses input focus, is different from that when it received focus.

  • onFocus : Triggers when a field receives input focus.

The message payload for these actions contains the name of the affected field, expressed in dot-notation if it is nested, and optionally the current value. The value is omitted if the field is blank.

For example:

{
    "payload": {
        "name": "nested.field1",
        "value": "some text"
    }
}

The message payload also receives an additional date property when the form field for which the action is triggered is configured to use a datepicker UI widget, but only if the current field value is a valid date. date is expressed as an Epoch number or an ISO UTC string depending on the field type in the schema.

For example, if the field type in the schema definition is "string" then the message payload will contain the additional date property expressed in ISO UTC format:

{
    "payload": {
        "name": "relative_date",
        "value": "*-1d",
        "date": "2023-01-04T14:44:58.733Z"
    }
}

If on the other hand it is defined as a "number", the date will be given as an epoch number:

{
    "payload": {
        "name": "epoch",
        "value": 1672963200000,
        "date": 1672963200000
    }
}
  • onSubmit : Gets called when the form submit button is pressed. The submit will not fire if there are validation error on the page.

    When the form is valid, the message payload will be the form data object. Only fields containing values will be present in the output.

  • onValidationError : Triggers when the form is submitted but there are validation errors.

    The message payload in this case is an array of error messages for all invalid fields.

For some combinations of field type and input-control, the value shown in the form and that saved to the data property of the work model is not exactly the same. This is the case with date-time fields, which are usually expressed in local time format in the UI, but saved as ISO UTC string in the model data property.

As seen earlier, when form actions are triggered, the message payload they receive contains the current UI field value, as opposed to the transformed data value. For date-time fields this is mostly not the case. The table below lists the payload value and date formats for date-time fields by action type.

The table columns have the following meaning:

  • Schema Type: Type of the date-time field as configured in the schema.

  • Convert Relative Date: How the convertRelativeDate property is set in the formOptions.entryOptions config for the field.

  • Value Entered: Value entered in the form field, where:

    • LT = String representing the local time.

    • UTC = String formatted as a ISO UTC time.

    • RT = A relative time expression

    • Epoch = Number of ms since the epoch start.

    • Bad = Some invalid number or text.

      • ε = The entered value is invalid and discarded by the form, which reverts back to the previous value entered

      • 𝝓 = The field is not present in the message.

  • Value Shown = The value shown in the form field once focus is lost.

  • <action name>

    • value = content of the value field in the message payload.

    • date = content of the date field in the message payload.

Here is an example model for a form field matching the first row in the table:

{
    "type": "advancedform",
    "formOptions": {
        "entryOptions": {
            "iso_date": {
                "convertRelativeDate": false, // Conv = false
                "actions": {
                    "onChange": {
                        "type": "send",
                        "to": "debugger"
                    }
                }
            }
        }
    },
    "schema": {
        "type": "object",
        "properties": {
            "iso_date": {
                "type": "string", // Schema type = string
                "title": "ISO Date"
            }
        }
    },
    "uiSchema": {
        "iso_date": {
            "ui:widget": "datepicker" // This is a date-time input field
        }
    }
}

when a local time is entered or selected from the time picker dialog, the onChange message looks something like this:

{
    "payload": {
        "name": "iso_date",
        "value": "2023-02-09 00:00:00.000", // Local time
        "date": "2023-02-09T00:00:00.000Z" // ISO UTC time
    }
}

Schema Type

Convert Relative Date

Value Entered

Value Shown

onFocus

onChange

onBlur

onChanged

value

date

value

date

value

date

value

date

String

False

LT

LT

UTC

UTC

LT

UTC

UTC

UTC

UTC

UTC

String

False

RT

RT

RT

RT

RT

RT

RT

RT

RT

RT

String

False

Epoch

LT

UTC

UTC

Epoch1

UTC

UTC

UTC

UTC

UTC

String

False

Bad

ε2

Bad

𝝓

Bad3

𝝓

String

String

RT

RT

RT

UTC

RT

UTC

RT

UTC

RT

UTC

String

Number4

RT

RT

RT

Epoch

RT

Epoch

RT

Epoch

RT

Epoch

Number

False

LT

LT

Epoch

Epoch

Epoch

Epoch

Epoch

Epoch

Epoch

Epoch

Number

False

RT

RT

RT

RT

RT

RT

RT

RT

RT

RT

Number

False

Epoch

LT

UTC

UTC

Epoch1

UTC

UTC

UTC

UTC

UTC

Number

False

Bad

ε2

Bad

𝝓

Bad3

𝝓

Number

String

RT

RT

RT

UTC

RT

UTC

RT

UTC

RT

UTC

Number

Number4

RT

RT

RT

Epoch

RT

Epoch

RT

Epoch

RT

Epoch

1 The epoch number is provided as a string.
2 The entered value is discarded once the field looses focus and reverts back to the last value. The onBlur and onChanged events also don’t trigger.
3 The value field shows the text entered in the form.
4 Converting a relative time value to an epoch number when the field type is set to "string" is technically an invalid configuration

Collect

The collect action can be used in an action pipeline to retrieve the current form data. The message payload will contain an object with entries for all fields that have a valid value.