Skip to main content

Forms

There are multiple layers that are considered form layers (e.g. the text box layer).

These layers have additional fields, most importantly the fields form and formDataKey. There are two ways in which a form can function, which is is determined by whether the form is set for a layer. This is called a named form. Using form layers without a form but using a formDataKey is called an anonymous form.

The main difference between using a named form and an anonymous form is that the named form is app-wide, while the anonymous form is bound to the currently shown view. This means that if the current view is destroyed, the data in an anonymous form is cleared, while the the data in the named form persists until it is manually cleared.

The form can be thought of as a JSON object storing data, while the formDataKeys are the keys in this object. Therefore, using the same formDataKey multiple times in the same form leads to a synchronization of these form layers. Keep in mind that using the same formDataKey in an insert layer layout will also result in this behavior.

It is also possible to influence the content of a form via actions:

Change of behavior of the value field

It is important to know that the value field works differently for form layers than for other layers. The value for a form layer should be seen as a fallback value rather than an actual value.

The priority with which a form layer receives its display value is:

  1. form value
  2. _settings value (given by the _settingsDataKey)
  3. value field

To set an initial value for a form layer, it is recommended to use the setFormValue action in combination with the viewCreated event.

Reading from a form

You can access a form via evaluables in conditions, dynamicParams and dynamicValues.
The context is different for named forms and anonymous forms. It is form for anonymous forms and namedForm for named forms. The value is the formDataKey for anonymous forms and formName:formDataKey for named forms.

onChanged and valueActions

There are two ways to react to value changes inside a form layer, the onChanged actions and the valueActions.

onChanged: The onChanged actions are executed every time the value has changed. This can happen by user interaction (e.g. a user is typing in a textBox), but also by the setFormValue action.

valueActions: The valueActions are an array of action arrays. The appropriate action for the value is chosen by its index. Only possible for form layers, where values have an index (i.e. selectBox, checkBox and slider). These actions are only executed by direct user interaction and not by calling the setFormValue action.

Form validation

The primary way to validate a form is via a regular expression. Every form layer has validationExpression field, which can be any regex. With the validateForm action, every validationExpression in the given form is checked, and only if all are valid, the onSuccess event is fired. Otherwise, the onError event is fired. You can also define a validationErrorMessage on every form layer. After calling the validateForm action, the error message of the first invalid form layer is shown as a toast.

If you want to display something visibly in order to mark the user input as invalid while the user is typing, you should use layer conditions and use a regex check there in combination with the form. This is executed every time the user changes the input.

Examples

Goal: Have a login form with an email and a password textBox and use their values for a request.

{
"type": "textBox",
"name": "email",
"formDataKey": "email",
"inputType": "email"
},
{
"type": "textBox",
"name": "password",
"formDataKey": "password",
"inputType": "password"
},
{
"type": "container",
"name": "submitContainer",
"actions": [
{
"type": "request",
"leadingDelimiter": "{$",
"trailingDelimiter": "$}",
"dynamicParams": {
"email": {
"context": "form",
"field": "email"
},
"password": {
"context": "form",
"field": "password"
}
},
"params": {
"url": "$env(baseUrl)$/authenticate",
"contentType": "json",
"method": "POST",
"post": {
"email": "{$email$}",
"password": "{$password$}"
}
}
}
]
}

Goal: Have a selectBox for an insert item representing the amount of a product in a shopping cart.

{
"type": "selectBox",
"name": "amount",
"onChanged": [
{
"type": "setDelimiters",
"params": {
"leadingDelimiter": "{$",
"trailingDelimiter": "$}"
}
},
{
"type": "executeSQL",
"params": {
"sql": "UPDATE cart SET amount = ? WHERE id = ?;",
"sqlParams": [
"{$amount$}",
"{{id}}"
]
}
}
]
}

Goal: Have a checkbox representing the setting of receiving push notifications and send the value of the checkbox via a request to the backend on change.

{
"type": "checkBox",
"images": [
"{{uncheckedImage}}",
"{{checkedImage}}"
],
"values": [
"false",
"true"
],
"valueActions": [
[
{
"type": "request",
"params": {
"url": "$env(baseUrl)$/profile",
"method": "POST",
"contentType": "json",
"post": {
"pushEnabled": false
}
}
}
],
[
{
"type": "request",
"params": {
"url": "$env(baseUrl)$/profile",
"method": "POST",
"contentType": "json",
"post": {
"pushEnabled": true
}
}
}
]
]
}