Binding Form Component Attributes

Various attributes of formComponents can be bound to data in state A direct reference constitutes two-way binding. As soon as a component’s value changes, the referenced value is automatically state and vice versa. Otherwise, it is a one-way binding. In this case, the value is only read from the state . For example, the value of a checkbox can be linked to the visibility of another Components.

The syntax for the binding is based on JS template strings and JSON pointer syntax. To declare a binding, ${} is used accordingly. Inside the parentheses is any expression using simplified JavaScript syntax. Using / —similar to JSON pointer syntax—elements from the state can be referenced. Note that this is simplified syntax and does not include the full range of functions. JS function calls are not possible.

{
  "type": "textfield",
  "label": "Two-Way binding",
  "value": "${/data/text}"
},
{
  "type": "textfield",
  "value": "One-Way binding: ${/data/text}"
}

Pointers may only contain the characters a–z, A–Z, 0–9, the underscore, and / to separate individual tokens. A single token references exactly one level of the state object. The pointer ${/data/text/example} therefore evaluates to Something if the state defined as follows: "state":{"data":{"text":{"example":"Something"}}}. The first token of a pointer cannot begin with 0–9. Subsequent tokens may begin with 0–9, provided that the token contains only 0–9 and no other characters. Other characters, such as umlauts or spaces, are not permitted in pointers.

{
  "type": "textfield",
  "value": "${/data/_a_0/0}"
}

Combining Values

Various operators are available for combining different values. Note that operators can only be evaluated within ${}. Outside of this context, no binding takes place, and operators—like everything else—are interpreted as text in that case.

Within the binding, the parentheses operator () is available. Strings, numbers, true, false, and null can be used as comparison values.

Boolean

The following operators are available for Boolean values: ! (logical NOT), && (logical AND), || (logical OR), ? : (If-Then-Else), ==, ===, !=, !==.

:filename:bindingBoolean.json .Example {filename}

Details
{filename}
Unresolved directive in previewCollapsed.adoc - include::example${filename}[]

Number

The following operators are available for numbers: +, -, *, /, >, >=, <, <=, ==, ===, !=, !==.

Example bindingNumber.json
bindingNumber.json
{
  "$schema": "https://forms.virtimo.net/5.0.x/schema.json",
  "metaData": {
    "id": 0,
    "version": 0
  },
  "configuration": {},
  "components": [
    {
      "type": "container",
      "label": "Number Binding",
      "components": [
        {
          "type": "html",
          "value": "Input"
        },
        {
          "type": "numberfield",
          "label": "A",
          "value": "${/data/A}"
        },
        {
          "type": "numberfield",
          "label": "B",
          "value": "${/data/B}"
        },
        {
          "type": "numberfield",
          "label": "C",
          "value": "${/data/C}"
        },
        {
          "type": "html",
          "value": "Output"
        },
        {
          "type": "html",
          "value": "A &times; B = ${/data/A * /data/B}"
        },
        {
          "type": "html",
          "value": "A &times; B ${/data/A * /data/B == /data/C ? '=' : '&ne;'} C"
        },
        {
          "type": "html",
          "value": "C &div; (B + A) = ${/data/C / (/data/B + /data/A)}"
        }
      ]
    }
  ],
  "state": {
    "data": {
      "A": 7,
      "B": 6,
      "C": 42
    }
  }
}

String

To combine strings, you can simply combine multiple bindings. Alternatively, strings can be concatenated within a binding using +. In this case, text must be enclosed in '.

Example bindingString.json
bindingString.json
{
  "$schema": "https://forms.virtimo.net/5.0.x/schema.json",
  "metaData": {
    "id": 0,
    "version": 0
  },
  "configuration": {},
  "components": [
    {
      "type": "container",
      "label": "String Binding",
      "components": [
        {
          "type": "html",
          "value": "Connecting more than ${/data/A} ${/data/B} values.${/data/Dot}"
        },
        {
          "type": "html",
          "value": "Alternative: ${'Connecting more than ' + /data/A + ' ' + /data/B + ' values' + /data/Dot}"
        }
      ]
    }
  ],
  "state": {
    "data": {
      "A": 2,
      "B": "string",
      "Dot": "."
    }
  }
}

Special Cases

Curly Braces (Escaping)

If ${ is used, this is automatically interpreted as the start of a binding. Binding with {} is not possible and should not be used, since in that case the entire binding is displayed as text without modification. With the exception of ${, {, and }, any characters can be used as text. If ${, {, or } are to appear as text, they must be included within the binding.

{
  "type": "html",
  "value": "Valid display of curly brackets: ${'}' + '${' + '{'}, other symbols: $%/()[]+'#-~1²"
}

Type Conversion

Components that expect a specific data type, such as checkbox or numberfield, automatically perform type conversion if necessary. The automatic conversion of primitive data types to strings, or of strings to numbers or dates, is unproblematic. However, for Booleans or when converting between non-string data types, the automatic conversion does not always yield the desired result. This should therefore be avoided or, in the case of Booleans, resolved using an operator.

{
  "type": "numberfield",
  "value": "${/data/number}"
},
{
  "type": "checkbox",
  "label": "Explicit Conversion from Number to Boolean",
  "value": "${/data/number > 0}",
  "disabled": true
},
{
  "type": "textfield",
  "label": "Automatic conversion from Number to String",
  "value": "${/data/number}",
  "disabled": true
}

Missing Values

If a pointer references a path that does not exist in the state , the entire binding is not evaluated. In this case, the value of the corresponding attribute is null.

Arrays and Nested Bindings

Nested bindings such as ${/data/items/${/data/index}} are not permitted. To access array elements with a dynamic index, a suitable Komponente such as combobox.

To overwrite values within an array, the table component should be used. Other components for displaying a single value, such as textfield, expect an object to be overwritten. These components should therefore not be used to overwrite values in an array.


Keywords: