Orbeon Forms
Search
K

Action syntax

Availability

This feature is available since Orbeon Forms 2018.2.

Rationale

Orbeon Forms supports services and actions. With Orbeon Forms 2018.2, a first step towards more powerful actions is introduced. There is no interface for it yet, but instead an XML configuration which you can paste into the form definition via the "Edit Source" dialog.

Enhancements

In addition to the features available through the "Actions" dialog, the following enhancements are available:
  • Call an action in response to multiple events.
  • Support more event types.
  • Call an arbitrary number of services.
  • Run actions without calling services.
  • Clear repeated grid or repeated section repetitions.
  • Add repeated grid or repeated section repetitions.
  • Repeatedly run parts of an action. [SINCE Orbeon Forms 2019.1]
  • Conditionally run parts of an action. [SINCE Orbeon Forms 2019.1]

Updating the form definition

You place listeners and actions within the source code, preferably before the end of the main <xf:model> content. For example:
<!-- other Form Builder code here -->
<fr:listener
version="2018.2"
.../>
<fr:action name="my-action" version="2018.2">
...
</fr:action>
<!-- Put `<fr:listener>` and `<fr:action>` just above this. -->
</xf:model>

Example

The following example:
  • listens to an activation event on the button my-button
  • in response, calls the my-action action, which
    • sets values from controls into the my-service service request
    • calls the my-service service
  • when the service call completes
    • the my-table repeated grid is cleared
    • iterating over the XML response, for each iteration
      • adds a repetition at the end of the my-table repeated grid
      • sets the value of controls on the new repetition
    • finally, all the result-dropdown dropdown control items are updated
<!-- other Form Builder code here -->
<fr:listener
version="2018.2"
events="activated"
controls="my-button"
actions="my-action"/>
<fr:action name="my-action" version="2018.2">
<fr:service-call service="my-service">
<fr:value control="foo" ref="/*/foo"/>
<fr:value control="bar" ref="/*/bar"/>
</fr:service-call>
<fr:repeat-clear repeat="my-table"/>
<fr:data-iterate ref="/*/row">
<fr:repeat-add-iteration repeat="my-table" at="end"/>
<fr:control-setvalue value="@field" control="result-field" at="end"/>
<fr:control-setvalue value="@dropdown" control="result-dropdown" at="end"/>
</fr:data-iterate>
<fr:control-setitems
items="/*/response/item"
label="@label"
value="@value"
control="result-dropdown"/>
</fr:action>
<!-- Put `<fr:listener>` and `<fr:action>` just above this. -->
</xf:model>

Listeners

Basic syntax

A listener looks like this:
<fr:listener
version="2018.2"
modes="..."
events="..."
controls="..."
actions="..."
>
Attribute
Mandatory
Value
Comment
version
Yes
format version
always 2018.2
modes
No
space-separated list of modes
The listener is enabled for each mode listed only. If absent, the listener is enabled for all modes.
events
Yes
space-separated list of event names
When more than one event name is present, the listener reacts if any of the listed events is present.
controls
Yes for events which relate to a particular control, like enabled or value-changed
space-separated list of control names
When more than one control name is present, the listener reacts if an event is dispatched to any of the listed controls.
actions
No, but nothing will happen if there is not at least one action referenced
space-separated list of action names
When more than one action name is present, all the specified actions are called when the listener reacts to an event.
NOTE: It is disallowed to mix and match, in a single listener, events for which a control name is required and events for which a control name is not required. Instead, use multiple listeners.

Modes supported

  • new
  • edit
  • view
  • pdf
xxx link to new modes page with explanations

Events supported

Controls:
  • enabled: the control has become enabled
  • disabled: the control has become disabled
  • visible: the control has become visible (for example in a wizard page)
  • hidden: the control has become hidden (for example in a wizard page)
  • value-changed: the value of an enabled control has changed
  • activated: the control has been activated (clicked, or enter in text field)
  • item-selected: an item of an enabled control has been selected
  • item-deselected: an item of an enabled control has been deselected
Form load:
  • form-load-before-data: run before the data's initial values are calculated
  • form-load-after-data: run when the data is ready
  • form-load-after-controls: run after the controls are ready
See also Running processes upon page load for the detail of the form load events.

Actions

Basic syntax

An action looks like this:
<fr:action
version="2018.2"
name="my-action"
>
Attribute
Mandatory
Value
Comment
version
Yes
format version
always 2018.2
name
Yes
action name
must be unique in the form definition

Control structures

Iterating over data

[SINCE Orbeon Forms 2019.1]

Basic usage

<fr:data-iterate ref="...expression...">
...
</fr:data-iterate>
<fr:data-iterate> allows you to iterate over data. The contained actions are executed once for each value returned by the expression.
Containing actions can include one or more calls to services.
Attribute
Mandatory
Value
Comment
ref
Yes
sequence XPath expression
runs in the current XPath evaluation context
In the following example, each repetition adds a row to the grid, calls a service, passing the attachment id, and sets the attachment value on the last row.
<fr:action name="populate-attachments" version="2018.2">
<fr:service-call service="get-attachments-list"/>
<fr:repeat-clear repeat="my-grid"/>
<fr:data-iterate ref="/*/row">
<fr:repeat-add-iteration repeat="my-grid" at="end"/>
<fr:service-call service="get-attachment">
<fr:url-param name="text" value="attachment-id"/>
</fr:service-call>
<fr:control-setattachment control="my-attachment" at="end"/>
</fr:data-iterate>
</fr:action>

Nesting of iterations

[SINCE Orbeon Forms 2019.2]
Calls to <fr:data-iterate> can be nested. This allows, for example, filling nested repeated sections and/or grids with the result of a service call that returns hierarchical data.
Example:
<fr:action name="my-action" version="2018.2">
<fr:service-call service="get-nobel-prizes"/>
<fr:repeat-clear repeat="prizes"/>
<fr:data-iterate ref="/*/prizes/_">
<fr:repeat-add-iteration repeat="prizes"/>
<fr:control-setvalue value="year" control="year" at="end"/>
<fr:control-setvalue value="category" control="category" at="end"/>
<fr:repeat-clear repeat="laureates"/>
<fr:data-iterate ref="laureates/_">
<fr:repeat-add-iteration repeat="laureates"/>
<fr:control-setvalue value="firstname" control="firstname" at="end"/>
<fr:control-setvalue value="surname" control="surname" at="end"/>
<fr:control-setvalue value="motivation" control="motivation" at="end"/>
</fr:data-iterate>
</fr:data-iterate>
</fr:action>

Conditions

[SINCE Orbeon Forms 2019.1]
<fr:if condition="...boolean expression...">
...
</fr:if>
<fr:if> allows you to conditionally run a block of actions.
Attribute
Mandatory
Value
Comment
condition
Yes
boolean XPath expression
runs in the current XPath evaluation context
In the following example, with the repetition performed by <fr:data-iterate>, the call to the service that retrieves an attachment depends on whether there is a non-blank attachment id provided.
<fr:action name="populate-attachments" version="2018.2">
<fr:service-call service="get-attachments-list"/>
<fr:repeat-clear repeat="my-grid"/>
<fr:data-iterate ref="/*/row">
<fr:repeat-add-iteration repeat="my-grid" at="end"/>
<fr:if condition="xxf:non-blank(attachment-id)">
<fr:service-call service="get-attachment">
<fr:url-param name="text" value="attachment-id"/>
</fr:service-call>
<fr:control-setattachment control="my-attachment" at="end"/>
</fr:if>
</fr:data-iterate>
</fr:action>

Asynchronous actions

Previously, actions were run synchronously. That is, they were blocking any other form processing until completed. It is now possible to run actions asynchronously. This means that the form processing can continue while the actions are running in the background. This is particularly useful when the actions call services.
You can enable asynchronous actions:
  • at the action level, using the async="true attribute
  • at the form level, using the oxf.fr.detail.actions.async.*.* property
Example of configuration property:
<property
as="xs:boolean"
name="oxf.fr.detail.actions.async.*.*"
value="true"/>
It is currently not possible to mix and match synchronous and asynchronous service calls within a given action.
An asynchronous action, by default, causes a response to the client (web browser) to wait forever for its completion. This is done to enhance the backward-compatibility of asynchronous actions. This can be disabled:
  • at the action level, using the response-must-await="0ms" attribute (or 0 followed by any other unit allowed as shown below)
  • at the form level, using the oxf.fr.detail.actions.response-must-await.*.* property
Example of configuration property:
<property
as="xs:string"
name="oxf.fr.detail.actions.response-must-await.*.*"
value="0ms"/>
If response-must-await is set to 0ms, a response to the client doesn't wait for the completion of asynchronous actions. Instead, the response is sent immediately, and the pending action's service calls continue to wait in the background. The client polls the server at regular intervals to check for the completion of such pending services, and then resumes the processing of the actions. This is useful when an action calls long-running services, and you don't want to keep the client waiting for its completion.
Possible values for this property and attribute are:
  • forever
  • "$length$unit" (whitespace allowed around and between tokens)
    • $length is a positive long integer value
    • $unit is as described below
Unit
Description
h
hours
m
minutes
s
seconds
ms
milliseconds
Practically, units in the ms and s ranges are the most useful.
Examples:
  • response-must-await="0ms": don't wait
  • response-must-await="200ms": wait up to 200 milliseconds
  • response-must-await="5s": wait up to 5 seconds
  • response-must-await="forever"`: wait indefinitely
For example, the Form Runner Landing page runs multiple background services to load lists of published forms. The page waits a few hundreds of milliseconds for the completion of those services, and if they take longer, for example due to a slow database, the page is shown to the user, and the services continue to run in the background.
In the future, asynchronous actions will likely be enabled by default.

Resolution of form controls

Many individual actions refer to form controls. When form controls are present in a repeated section or repeated grid, there can be ambiguity as to which control is being referred to.
For this reason, an optional at attribute can be specified. That attribute is a space-separated list of tokens, one for each repetition level.
A token can take the following values:
  • start: the first repetition
  • end: the last repetition
  • a strictly positive integer: the repetition at that specific position
  • all: all controls [SINCE Orbeon Forms 2023.1]
When the at attribute is not present, it defaults to being relative to the action source. This usually means targeting the first repetition.
The following example sets the value of the control my-repeated-value in all repetitions of the my-repeated-value repeated grid to 42
<fr:control-setvalue
value="'42'"
control="my-repeated-value"
at="all"/>
Assume now that the control my-repeated-value is within a repeated grid, itself nested within two levels of repeated sections. The following example sets the value of the control my-repeated-value in the third repetition of the last repetition of the first repetition to 42:
<fr:control-setvalue
value="'42'"
control="my-repeated-value"
at="start end 3"/>

Individual actions

Calling a service

<fr:service-call service="...service name...">
<fr:value value="..." ref="..."/>
</fr:service-call>
<fr:service-call> calls a service by name.
Attribute
Mandatory
Value
Comment
service
Yes
name of the service to call
must be an existing service

Passing a value

<fr:value value="..." ref="..."/>
or:
<fr:value control="..." ref="..."/>
When calling an HTTP service, you can set XML request body values using nested <fr:value> elements.
Attribute
Mandatory
Value
Comment
control
No
control name
either this or value must be specified
value
No
value expression
either this or control must be specified
ref
Yes
destination expression
points to an element or attribute in the request XML

Passing a URL parameter

<fr:url-param name="..." value="..."/>
When calling an HTTP service, you can pass URL parameters using nested <fr:url-param> elements.
Attribute
Mandatory
Value
Comment
control
No
control name
either this or value must be specified
value
No
value expression
either this or control must be specified
name
Yes
parameter name
URL parameter name

Passing a SQL parameter

<fr:sql-param index="..." value="..."/>
When calling a database service, you can pass parameters using nested <fr:sql-param> elements.
Attribute
Mandatory
Value
Comment
control
No
control name
either this or value must be specified
value
No
value expression
either this or control must be specified
index
Yes
positive integer
SQL query parameter index

Removing all repetitions of a repeat

<fr:repeat-clear
repeat="..."
at="..."/>
Attribute
Mandatory
Value
Comment
repeat
Yes
repeated grid or repeated section name
at
No
space-delimited position tokens: start, end, or a positive integer
missing leading tokens default to end
This action starts by identifying a single repeated grid or section with the repeat attribute. See <fr:repeat-add-iteration> for details. The only difference is that with this action, at is only used to identify the ancestor repeated sections if any.
With my-repeated-grid nested within my-repeated-section:
  • Remove all repetitions of my-repeated-section:
    <fr:repeat-clear repeat="my-repeated-section"/>
  • Remove all repetitions of the last my-repeated-grid:
    <fr:repeat-clear repeat="my-repeated-grid" at="end"/>
  • Remove all repetitions of the first my-repeated-grid:
    <fr:repeat-clear repeat="my-repeated-grid" at="start"/>
  • Remove all repetitions of the second my-repeated-grid:
    <fr:repeat-clear repeat="my-repeated-grid" at="2"/>

Adding repetitions to a repeat

<fr:repeat-add-iteration
repeat="..."
at="..."/>
Attribute
Mandatory
Value
Comment
repeat
Yes
repeated grid or repeated section name
at
No
space-delimited position tokens: start, end, or a positive integer
missing leading tokens default to end
This action starts by identifying a single repeated grid or section with the repeat attribute. If the repeated grid or section is at the top-level, there is only one possible match. If the repeated grid or section is nested within one or more repeated sections, then a single repetition of the ancestor repeated sections is determined using the optional at attribute.
With my-repeated-grid nested within my-repeated-section:
  • Insert a new repetition at the end of the last my-repeated-grid:
    <fr:repeat-add-iteration repeat="my-repeated-grid" at="end end"/>
    or:
    <fr:repeat-add-iteration repeat="my-repeated-grid" at="end"/>
    or:
    <fr:repeat-add-iteration repeat="my-repeated-grid"/>
  • Insert a new repetition at the end of the first my-repeated-grid:
    <fr:repeat-add-iteration repeat="my-repeated-grid" at="start end"/>
  • Insert a new repetition at the start of the first my-repeated-grid:
    <fr:repeat-add-iteration repeat="my-repeated-grid" at="start start"/>
  • Insert a new repetition after repetition 2 of the third my-repeated-grid:
    <fr:repeat-add-iteration repeat="my-repeated-grid" at="3 2"/>
  • Insert a new repetition at the end of my-repeated-section:
    <fr:repeat-add-iteration repeat="my-repeated-section" at="end"/>
    or:
    <fr:repeat-add-iteration repeat="my-repeated-section"/>

Removing repetitions from a repeat

<fr:repeat-remove-iteration
repeat="..."
at="..."/>
Attribute
Mandatory
Value
Comment
repeat
Yes
repeated grid or repeated section name
at
No
space-delimited position tokens: start, end, or a positive integer
missing leading tokens default to end
This action starts by identifying a single repeated grid or section with the repeat attribute. See <fr:repeat-add-iteration> for details.
With my-repeated-grid nested within my-repeated-section:
  • Remove the last repetition of the last my-repeated-grid:
    <fr:repeat-remove-iteration repeat="my-repeated-grid" at="end end"/>
    or:
    <fr:repeat-remove-iteration repeat="my-repeated-grid" at="end"/>
    or:
    <fr:repeat-remove-iteration repeat="my-repeated-grid"/>
  • Remove the last repetition of the first my-repeated-grid:
    <fr:repeat-remove-iteration repeat="my-repeated-grid" at="start end"/>
  • Remove repetition 2 of the third my-repeated-grid:
    <fr:repeat-remove-iteration repeat="my-repeated-grid" at="3 2"/>

Setting the value of a control

<fr:control-setvalue/>
<fr:control-setvalue/> sets the value of a form control.
Attribute
Mandatory
Value
Comment
control
Yes
control name
value
Yes
value expression
value to set
at
No
space-delimited position tokens: start, end, or a positive integer
missing leading tokens default to end
<fr:control-setvalue
control="my-control"
value="current-date()"/>

Clearing the value of a control

[SINCE Orbeon Forms 2020.1]
<fr:control-clear/>
<fr:control-clear/> clears the value of a control. For attachment controls, this clears the file but also the file metadata (filename, mediatype, and size).
Attribute
Mandatory
Value
Comment
control
Yes
control name
at
No
space-delimited position tokens: start, end, or a positive integer
missing leading tokens default to end
Example:
<fr:control-clear control="my-control"/>

Setting the choices of a selection control

<fr:control-setitems/>