Dynamic Computation¶
Available from version 2.26.0. Configure a form element to automatically compute the sum (or other transformation) of values from repeatable elements, updating in real time as the user fills in the form.
The pattern: emitter and subscriber¶
Dynamic computation uses an event system with two roles:
- Emitter — a source element (inside a repeatable section) that publishes its value when it changes
- Subscriber — a target element that receives the emitted values and applies a transformation to compute a result
Configuring the emitter¶
The emitter is inside a repeatable section. Add computationConfig to the element that should be summed:
{
"key": "retentionValue",
"label": "Retention Value",
"type": "numeric-input",
"computationConfig": {
"emitter": {
"eventName": "retention-total-event"
}
}
}
The eventName must be unique across the entire application.
Configuring the subscriber¶
The subscriber is the target field that displays the computed result. It should be non-editable:
{
"key": "totalRetentionValue",
"label": "Total Retention",
"type": "numeric-input",
"modifierClass": "non-editable",
"computationConfig": {
"subscriber": {
"eventName": "retention-total-event",
"transformExpression": "model?.reduce((sum, el) => sum + Number(el.retentionValue), 0) || 0"
}
}
}
The transformExpression is a JavaScript expression. model contains the array of emitted values (one per repeatable row). The expression above sums the retentionValue field from each row.
Alternative: computationSourceFormPath¶
Use computationSourceFormPath instead of eventName when multiple instances of the same screen exist (e.g. multiple products, each with its own retention repeatable). This binds to a specific form path without event emission, avoiding cross-instance interference:
{
"computationConfig": {
"subscriber": {
"computationSourceFormPath": "productCoverDetail.data.retentions",
"transformExpression": "model?.reduce((sum, el) => sum + Number(el.retentionValue), 0) || 0"
}
}
}
Tips¶
- Event names must be globally unique. Use a descriptive name that includes the business class or action name to avoid collisions.
- The subscriber field should always be
modifierClass: "non-editable"— it is a computed field, not a user input. - The
transformExpressionruns in the browser. Standard JavaScript array methods (reduce,map,filter) are available. - If
modelis null or empty (no rows added yet), the|| 0guard preventsNaNfrom being displayed.
Common expressions¶
Sum a numeric field from all rows:
Count the number of rows:
Sum only rows where a condition is true: