Custom modes
Availability
[SINCE Orbeon Forms 2025.1]
NOTE: This is an advanced feature which may require programming skills.
Introduction
The Form Runner Detail page is the page where users create, edit, and view form data. Each such function is referred to as a mode. For more, see Form Runner detail page modes.
Orbeon Forms 2025.1 introduces the ability to define custom modes for the Form Runner Detail page. This allows you to create different views of the same form data. You do so by writing a custom component, while Orbeon Forms handles data management, state keeping, and permissions for you.
Custom modes are supported by functions to:
navigate away from Orbeon Forms to external pages, or pages embedded in iframes
navigate back to Orbeon Forms, while keeping the form data and other state information
However, custom modes can be used separately from these functions, and conversely these functions can be used without custom modes.
Here is an example of workflow involving standard modes, a custom mode, an external page or service, and navigation back to Orbeon Forms:

An important use case for this is calling external services such as:
payment providers
signature providers
and more.
Defining custom modes
A custom mode has to be defined before it can be used. You do so with the oxf.fr.detail.custom-modes.*.*
property. The property value is a JSON array of objects, each object defining a custom mode.
As usual, with wildcards representing the application name and form name, you can define custom modes for all forms, for all forms in a specific application, or for a specific form.
<property as="xs:string" name="oxf.fr.detail.custom-modes.*.*" xmlns:acme="http://www.acme.com/xbl">
[
{
"name": "acme:demo-sign",
"mode-type": "readonly",
"persistence": false
}
]
</property>
The
name
attribute is the name of the custom mode.This must be an XML qualified name with a prefix and a colon
:
. Unqualified names are reserved for builtin modes.The prefix, here
acme
, must be defined in thexmlns
attribute of the property or the properties file, herexmlns:acme="http://www.acme.com/xbl"
.A matching XBL component of the same name will be used as view component, here
acme:demo-sign
.
The
mode-type
attribute defines the type of the custom mode. It can be one of the following values:readonly
: the form is displayed in read-only mode, and users cannot change or save any data.edition
: the form is displayed in edit mode, and users can change data and save data, given appropriate permissions.
The
persistence
attribute defines whether the mode is allowed to read/write data from/to the persistence layer.If
true
, the mode is allowed to access the persistence layer, given appropriate permissions.If
false
, the mode is not allowed to access the persistence layer.In this case, form data typically comes from navigation from another mode, or from state restoration, and is passed to another mode or saved through
fr:save-state()
.
Custom mode names appear in URLS, for example:
/fr/orbeon/feedback/fr:demo-sign/9eff349bfd95aab8d4d5e048bd25a815
Saving state
Form state includes:
the current form data
the current application name, form name, and form version
the current mode
the current workflow stage
current form permissions
and more
When navigating away from Orbeon Forms, you typically want to save that state, so that when the user comes back to Orbeon Forms, they can continue where they left off.
A new function is provided to save the current state of the form data, and other information, and return a token which can be used later to restore that state:
fr:save-state() as xs:string
fr:save-state(
$continuation-mode as xs:string?
) as xs:string
fr:save-state(
$continuation-mode as xs:string?,
$continuation-workflow-state as xs:string?
) as xs:string
The parameters are optional:
$continuation-mode
:If provided, when the user comes back to Orbeon Forms, they will be put in that mode.
If not provided, they will be put in the same mode as when
fr:save-state()
was called.
$continuation-workflow-state
:If provided, when the user comes back to Orbeon Forms, they will be put in that workflow state.
If not provided, they will be put in the same workflow state as when
fr:save-state()
was called.
This function can be called from a button process, for example:
<property as="xs:string" name="oxf.fr.detail.process.demo-external-sign.*.*">
navigate("https://example.org/signature?token={encode-for-uri(fr:save-state('view'))}")
</property>
A side effect of calling this function is that the form state, as described above, is serialized, encrypted, and temporarily saved into a server-side store.
In addition, a token is created, which allows later restoration of the state (see below).
The token includes an expiration time, which is 15 minutes by default. The idea is that the user will leave Orbeon Forms temporarily to perform a task, but will come back to Orbeon Forms relatively soon in most cases. This can be important as storing the state requires some resources on the server side.
You can change the token expiration time in minutes by setting the following property:
<property
as="xs:integer"
name="oxf.fr.state-token.validity.*.*"
value="15"/>
Restoring state
Orbeon Forms provides a new callback endpoint:
/fr/callback?token=...
This must be reached with an HTTP GET
. When called, the callback:
checks that a valid, non-expired token is provided
obtain the state from the store
navigates to the Detail page, restoring the state that was stored
is a continuation mode was specified with
fr:save-state()
, Form Runner switches to that mode, otherwise uses the same mode as whenfr:save-state()
was calledif a continuation workflow stage was specified with
fr:save-state()
, Form Runner switches to that workflow state, otherwise uses the same workflow stage as whenfr:save-state()
was called
Implementing a view component
The mode's qualified name determines the name of the XBL view component. Like for any custom component, an explicit mapping from prefix to namespace must be provided, for example:
<property
as="xs:string"
name="oxf.xforms.xbl.mapping.acme"
value="http://www.acme.com/xbl" />
See also XBL Bindings for more about defining custom components.
You place your component files in the xbl
directory, for example:
WEB-INF/resources/xbl/acme/demo-sign/demo-sign.xbl
Here is a simple example of a view component implemented by a demo-sign.xbl
:
<xbl:xbl
xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
xmlns:acme="http://www.acme.com/xbl">
<xbl:binding
id="acme-demo-sign"
element="acme|demo-sign"
xxbl:container="div"
xxbl:mode=""
>
<xbl:template>
<xh:div>
This is the signature page.
</xh:div>
</xbl:template>
</xbl:binding>
</xbl:xbl>
This component simply displays a message. In a real-world scenario, you would do more, for example:
show the values of some form fields
embed an
iframe
or other content with JavaScriptcall external services
and more.
The change-mode()
action
change-mode()
actionThe change-mode()
action allows you to navigate to any mode, including custom modes. Examples:
change-mode("edit")
: This action navigates to theedit
mode from any mode, and is identical to theedit
action.change-mode("view")
: This action navigates to theview
mode from any mode, and is identical to thereview
action.change-mode("new")
: This action navigates to thenew
mode from any mode.change-mode("acme:demo-sign")
: This action navigates to the customacme:demo-sign
mode from any mode.
NOTE: It is not possible to use this action to produce a pdf
or tiff
view of the form data. Use the open-rendered-format()
action instead.
Configuring buttons
Navigating to a custom mode
Say you are on the new
or edit
page, and want to add a button to navigate to your custom signature page. You can do so by defining a custom demo-sign
button using the oxf.fr.detail.buttons.*.*
property. For example:
<property as="xs:string" name="oxf.fr.detail.buttons.*.*">
demo-sign
</property>
You must also assign a label to that button:
<property as="xs:string" name="oxf.fr.resource.*.*.en.buttons.demo-sign">
<i class="fa fa-fw fa-file-signature"></i> Demo Sign
</property>
Finally, assign a simple process to that button which changes the mode to your custom mode:
<property as="xs:string" name="oxf.fr.detail.process.demo-sign.*.*">
change-mode(mode = "acme:demo-sign")
</property>
As usual, the wildcards in the property names can be replaced by specific application and form names.
The result will be a button on the new
or edit
page which, when clicked, will switch to your custom signature page, while keeping data and state.

Buttons on custom mode pages
You configure buttons on custom mode pages using the oxf.fr.detail.buttons.*.*.*
property. For example, to add a button which calls fr:save-state()
and navigates to an external signature provider, you could use:
<property as="xs:string" name="oxf.fr.detail.buttons.acme:demo-sign.*.*">
new demo-external-sign
</property>
The new
button can be configured to navigate back to the new
mode. The demo-external-sign
button can be configured to call fr:save-state()
and navigate to an external signature provider.
<property as="xs:string" name="oxf.fr.detail.process.new.*.*">
change-mode(mode = "new")
</property>
<property as="xs:string" name="oxf.fr.resource.*.*.en.buttons.demo-external-sign">
<i class="fa fa-fw fa-file-signature"></i> Demo External Sign
</property>
<property as="xs:string" name="oxf.fr.detail.process.demo-external-sign.*.*">
navigate("https://example.org/signature?token={encode-for-uri(fr:save-state('view'))}")
</property>
A very important part is the call to fr:save-state('view')
, which saves the current state, and specifies that when the user comes back to Orbeon Forms, they should be put in the view
mode.
Note the encode-for-uri()
call, which ensures that the token is properly encoded for use in a URL.
The external service provider must be configured to call back to Orbeon Forms at the /fr/callback?token=...
endpoint. When the user comes back to Orbeon Forms, they will be put in the view
mode, and see the form data in read-only mode.
Security considerations
Form state is sensitive information, and Orbeon Forms makes sure to handle it securely:
the form state is encrypted on the server using the encryption password
the server store is configured to expire items after a certain time
the token does not expose sensitive information
the token can only be used once; a second use returns an error
form state is removed from the server store once it has been used
See also
Last updated