Skip to main content
Version: 2.4

Fluent Array

The dtl-fluent-array widget is used for visualization and management of arrays in a form. It allows dynamic addition and removal of items.

Choose the row structure first

An array repeats its item schema. Decide whether one row is a single value or an object with several named fields before adding widgets.

Row contentItem schemaExample form value
One text valueitems.type: "string"{"rows": ["A", "B"]}
Several fieldsitems.type: "object" with properties{"rows": [{"source": "A", "target": "B"}]}

Build a row with two fields in the Designer

  1. Add an Array to the form.
  2. Drop an Object into the empty Array to define an object row.
  3. Drop two Text widgets inside that Object. Use the Object's drop area, rather than a sibling drop area on the outer Array.
  4. Name the fields source and target. Set the target to read-only if an effect will calculate it.
  5. Open the form preview, add two rows, and check that each row contains both fields.

The data schema for these rows is:

{
"rows": {
"type": "array",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string",
"title": "Source",
"widget": {
"type": "text"
}
},
"target": {
"type": "string",
"title": "Target",
"widget": {
"type": "text"
}
}
}
}
}
}

This fragment belongs under the root properties. The Designer also creates layout references for the fields. See the complete copy-per-row example for a form you can paste into the schema editor.

For nested groups and lines, repeat the same structure: Array → Object → Array → Object → Text fields. The outer object owns lines; the inner object owns source and target.

Why a second direct text drop does not create another field

Dropping a Text directly into an empty Array creates scalar items:

{
"type": "array",
"items": {
"type": "string",
"widget": {
"type": "text"
}
}
}

This describes a list of strings. A second widget cannot become a named field of that string. A row with source and target needs an object item instead.

Older Designer versions could add items.properties.text and a layout reference such as rows!.text while leaving items.type as string. The added field was invisible because the schema mixed scalar and object structures.

With the incompatible-drop fix (MR !3548), the Designer warns and leaves the schema unchanged. This does not convert existing string arrays to object arrays or repair previously malformed schemas. For a new form, recreate the Array using an Object row. For a saved form with data or effects, changing the row structure also requires adapting those values and paths.

Layouts inside an array

You can insert layouts (tabs, columns, etc.) directly into an object-row array.

array
{
"type": "object",
"widget": {
"type": "dtl-fluent-section"
},
"properties": {
"array": {
"type": "array",
"widget": {
"type": "dtl-fluent-array"
},
"items": {
"type": "object",
"widget": {
"type": "dtl-fluent-object"
},
"properties": {
"text": {
"type": "string",
"title": "Text",
"widget": {
"type": "text"
}
},
"textarea": {
"type": "string",
"title": "Textarea",
"widget": {
"type": "textarea"
}
}
}
},
"config": {
"numberOfRows": {
"value": 0,
"onlyForEmpty": true
}
}
}
},
"layout": [
{
"type": "layout",
"items": [
{
"propertyKey": "array",
"type": "layout",
"items": [
{
"type": "layout",
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [
"array!.text"
]
},
"array!.textarea"
],
"config": {
"columns": [
{
"width": 6,
"content": [
1
]
},
{
"width": 6,
"content": [
0
]
}
],
"innerPageLayout": false
},
"widget": {
"type": "dtl-fluent-columns"
}
}
],
"widget": {
"type": "dtl-fluent-array"
}
}
],
"config": {
"columns": [
{
"width": 6,
"content": [
0
]
},
{
"width": 6
}
],
"innerPageLayout": false
},
"widget": {
"type": "dtl-fluent-columns"
}
}
]
}
Widget Reference

For a complete list of configuration options for the dtl-fluent-array widget, see the Advanced Widgets Reference.