xs:base64Binary
type.
XForms Reference, Part 2
- 1. Introduction
- 2. Extensions
- 2.1. Read-Only Mode
- 2.2. Formatting
- 2.2.1. Rationale
- 2.2.2. xforms:input
- 2.2.3. xforms:output
- 2.2.4. Default Formatting
- 2.3. XForms 1.1 Extensions
- 2.4. XPath Extension Functions
- 2.4.1. XSLT 2.0 Functions
- 2.4.2. Orbeon Forms Functions
- 2.4.3. eXForms Functions
- 2.5. JavaScript Integration
- 2.5.1. Rationale
- 2.5.2. Getting and Setting Controls Value
- 2.5.3. Dispatching Events
- 2.6. Attribute Value Templates
- 2.7. Dialogs
- 2.8. Other Extensions
- 2.8.1. XForms Submission - HTTP Authentication
- 2.8.2. XForms Submission/Load - Loading Indicator
- 2.8.3. XForms Submission/Load - Target
- 2.8.4. xxforms:script Action
- 2.8.5. Read-Only XForms Instances with xxforms:readonly
- 2.8.6. Sharing of Read-Only XForms Instances with xxforms:shared
- 2.8.7. Controlling Item Sets Refreshes with xxforms:refresh-items
- 2.8.8. Trees with the xxforms:tree Appearance
- 2.8.9. Menus with the xxforms:menu Appearance
- 3. Configuration
- 3.1. State Handling
- 3.1.1. Rationale
- 3.1.2. Configuring State Handling
- 3.2. JavaScript and CSS Resources
- 3.2.1. Minimal Resources
- 3.2.2. Combined Resources
- 3.3. Debugging XForms Pages
- 3.3.1. Enabling XForms Logging
- 3.3.2. The Instance Inspector
- 3.1. State Handling
- 4. Migrating from XForms Classic to XForms NG
1. Introduction
This is Part 2 of a two-part document. This part focuses on extensions over XForms provided by Orbeon Forms, as well as XForms engine configuration.
Please be sure to visit Part 1 as well.
2. Extensions
2.1. Read-Only Mode
2.1.1. Making an Entire Instance Read-Only
You often want to present a form without allowing the user to enter data. An easy solution is to use
the readonly
MIP in the model. By making for example the root element of an instance
read-only, all the controls bound to any node of that instance will appear read-only (because the
read-only property is inherited in an instance):
2.1.2. Static Appearance for Read-Only Mode
Sometimes, read-only controls don't appear very nicely in web browsers. For example, a combo box will appear grayed out. It maybe be hard to read, and there is not much point showing a combo box since the user can't interact with it. Furthermore, with some browsers, like IE 6 and earlier, it is not even possible to make disabled controls appear nicer with CSS. In order to make read-only versions of forms look nicer, Orbeon Forms supports a special extention attribute that allows you to produce a "static" appearance for read-only controls. You enable this on your first XForms model:
The attribute takes one of two vales: static
or dynamic
(the default).
When using the value static
, read-only controls do not produce disabled HTML form
controls. This has one major limitation: you can't switch a control back to being read-write once
it is displayed as read-only.
You can also set the xxforms:readonly-appearance
attribute directly on individual
XForms controls.
See the Government Forms sample application's View Read-Only option for an example of this feature in action.
2.2. Formatting
2.2.1. Rationale
It is usually recommended to use native XML types within XForms instances, as this guarantees
interoperability and maintainability. For example, a date of January 10, 2005 is stored in ISO
format as: 2005-10-01
. However it is often necessary to format such values on screen
in a user-readable format, like "January 10, 2005", "10 janvier 2005", or "10. Januar 2005".
Orbeon Forms provides an extension attribute, xxforms:format
, for that purpose.
xxforms:format
must contain an XPath 2.0 expression. In your XPath expression you can
use all the XPath 2.0 functions, including those for date manipulation (external
documentation). However since XPath 2.0 functions don't provide any facility for date and time
formatting, you can in this attribute also use the following XSLT 2.0 functions:
-
format-date()
(external documentation) -
format-dateTime()
(external documentation) -
format-time()
(external documentation) -
format-number()
(external documentation)
The XPath expression is evaluated by the XForms engine whenever the value bound to the
xforms:input
control changes and needs to be updated on screen. It is evaluated in the
context of the instance node bound to the control. This means that the current value of the control
can be accessed with ".
". Often the value must be converted (for example to a date) in
which case the conversion can be done with a XPath 2.0 constructor such as xs:date(.)
or with as cast such as (. cast as xs:date?)
.
2.2.2. xforms:input
When using xforms:input
and a bound xs:date
type, you can control the
formatting of the date using the xxforms:format
extension attribute on the
xforms:input
control. For example:
2.2.3. xforms:output
When using xforms:output
, you can control the formatting of the date using the
xxforms:format
extension attribute on the xforms:output
control.
2.2.4. Default Formatting
For both xforms:input
and xforms:output
, if the bound node is of one of
the following types: xs:date
, xs:dateTime
, xs:time
,
xs:decimal
, xs:integer
, xs:float
, and xs:double
,
and if no xxforms:format
attribute is present on the control, formatting is based on
properties. If the properties are missing, a built-in default
formatting is used. The default properties, as well as the built-in defaults, are as follows:
They produce results as follows:
-
2004-01-07
asxs:date
is displayed asWednesday January 7, 2004
-
2004-01-07T04:38:35.123
asxs:dateTime
is displayed asWednesday January 7, 2004 04:38:35 UTC
-
04:38:35.123
asxs:time
is displayed as04:38:35 UTC
-
123456.789
asxs:decimal
is displayed as123,456.79
-
123456.789
asxs:integer
is displayed as123,456
-
123456.789
asxs:float
orxs:double
is displayed as123,456.789
Note:
- With the "if" condition in the XPath expressions, a value which cannot be converted to the appropriate type is simply displayed as is.
- For values of type xs:time or xs:dateTime, if you wish the time to be displayed using the current timezone instead of UTC, replace in the value attribute UTC by [ZN].
2.3. XForms 1.1 Extensions
2.3.1. Media Type for xforms:output
In XForms 1.0, xforms:output
is used to display text. However, based on a proposal
in a draft version of XForms 1.1, Orbeon Forms supports a mediatype
attribute on
that element.
For the <xforms:output>
control to display an image, you
need to:
-
Have a
mediatype
attribute on the<xforms:output>
. That attribute must refer to an image, such asimage/*
orimage/jpeg
. -
Use the
value
attribute on<xforms:output>
or bind to the control to a node without type or with anxs:anyURI
type.
The resulting value is interpreted a URI pointing to an image. The image
will display in place of the xforms:output
. When a single-node
binding is used, it is possible to dynamically change the image pointed to.
For example:
When an xforms:output
control has a mediatype
attribute with value text/html
, the value of the node to which
the control is bound is interpreted as HTML content. Consider the following
XForms instance:
You bind an xforms:output
control to the
html-content
node as follows:
This will display the result as HTML, as expected: "This is in bold!". If the
mediatype
is not specified, the result would be instead: "This is in
<b>bold</b>!". In the XForms instance, the HTML content must be escaped as text. On
the other hand, the following content will not work as expected:
mediatype="text/html"
, an HTML
<div>
element will be generated by the XForms engine to hold
the HTML data. As in HTML a <div>
cannot
be embedded into a <p>
, if you have a
<xforms:output mediatype="text/html">
control, you should
not put that control into a <xhtml:p>
.
2.3.2. origin Attribute on xforms:insert Action
Orbeon Forms supports the XForms 1.1 origin
attribute on the
xforms:insert
action. This attribute allows specifying the source node to use as
template. This allows storing templates separately from the node-set specified by the
nodeset
attribute. For example:
The template copied in this case comes from an XForms instance:
2.3.3. context Attribute on xforms:insert Action
Orbeon Forms supports the XForms 1.1 context
attribute on the
xforms:insert
action. This attribute allows specifying a context for insertion,
which along with the origin
attribute allows inserting content into elements:
With original instances as follows:
The result of a first insertion is:
2.3.4. validate and relevant Attributes on xforms:submission
Orbeon Forms supports the XForms 1.1 validate
and relevant
attributes
on xforms:submission
. For more information, please visit the XForms 1.1 specification.
2.3.5. Conditional Execution and Iteration of XForms Actions
Orbeon Forms supports the XForms 1.1 if
and while
attributes on XForms
action elements. For more information, please visit the XForms 1.1 specification.
2.4. XPath Extension Functions
Orbeon Forms implements some extension functions which can be used from XPath expressions in XForms documents.
2.4.1. XSLT 2.0 Functions
When using XPath 2.0, the following functions from XSLT 2.0 are also available:
-
format-date()
(external documentation) -
format-dateTime()
(external documentation) -
format-time()
(external documentation) -
format-number()
(external documentation)
2.4.2. Orbeon Forms Functions
The following functions are implemented:
-
xxforms:if()
.This function implements the semantic of the XForms 1.0
if()
function. See Note About XPath 2.0 Expressions for more details. -
xxforms:call-xpl($xplURL as xs:string, $inputNames as xs:string*, $inputElements as element()*, $outputNames as xs:string+) as document-node()*
.This function lets you call an XPL pipeline.
-
The first argument,
$XPLurl
, is the URL of the pipeline. It must be an absolute URL. -
The second argument,
$inputNames
, is a sequence of strings, each one representing the name of an input of the pipeline that you want to connect. -
The third argument,
$inputElements
, is a sequence of elements to be used as input for the pipeline. The$inputNames
and$inputElements
sequences must have the same length. For each element in$inputElements
, a document is created and connected to an input of the pipeline. Elements are matched to input name by position, for instance the element at position 3 of$inputElements
is connected to the input with the name specified at position 3 in$inputNames
. -
The fourth argument,
$outputNames
, is a sequence of output names to read. -
The function returns a sequence of document nodes corresponding the output of the
pipeline. The returned sequence will have the same length as
$outputNames
and will correspond to the pipeline output with the name specified on$outputNames
based on position.
The example below shows a call to the
xxforms:call-xpl
function:xxforms:call-xpl ('oxf:/examples/sandbox/xpath/run-xpath.xpl', ('input', 'xpath'), (instance('instance')/input, instance('instance')/xpath), 'formatted-output')/*, 'html') -
The first argument,
-
xxforms:evaluate($xpath as xs:string) as item()*
.The
xxforms:evaluate()
function allows you to evaluate XPath expressions dynamically. For example:<xforms:input ref="xxforms:evaluate(concat('instance(''my-instance'')/document', my-xpath))"><xforms:label>...</xforms:label></xforms:input> -
xxforms:serialize($item as node(), $format as xs:string?) as xs:string
.The
xxforms:serialize()
function allows you to serialize an XML node to XML, HTML, XHTML or text. For example:<xforms:bind nodeset="my-html" calculate="xxforms:serialize(instance('my-instance'), 'html')"/> -
xxforms:repeat-current($repeat-id as xs:string?) as node()
.The
xxforms:repeat-current()
function allows you to obtain a reference to an enclosingxforms:repeat
's current iteration node. It takes one optional string parameter. If present, the id of the enclosingxforms:repeat
is searched. If absent, the function looks for the closest enclosingxforms:repeat
.<xforms:repeat nodeset="employee" id="employee-repeat"><tr><td><!-- The context is being set to another instance that controls the visibility of the group. --><xforms:group ref="instance('control-instance')/input"><!-- Using xxforms:repeat-current() allows reclaiming the context of the repeat iteration. --><xforms:input ref="xxforms:repeat-current('employee-repeat')/name"><xforms:label>Employee Name</xforms:label></xforms:input></xforms:group></td></tr></xforms:repeat>The
xxforms:repeat-current()
function must be called from within anxforms:repeat
element. -
xxforms:context($element-id as xs:string?) as node()
.The
xxforms:context()
function allows you to obtain the evaluation context for an enclosingxforms:group
,xforms:repeat
, orxforms:switch
. It takes one optional string parameter containing the id of an enclosing XForms element.<xforms:group ref="employee" id="employee-group"><!-- The context is being set to another instance that controls the visibility of the group. --><xforms:group ref="instance('control-instance')/input"><!-- Using xxforms:context() allows reclaiming the context of the enclosing group. --><xforms:input ref="xxforms:context('employee-group')/name"><xforms:label>Employee Name</xforms:label></xforms:input></xforms:group></xforms:group> -
xxforms:instance($instance-id as xs:string) as element()?
.The
xxforms:instance()
function works like the standardinstance()
function except that it searches for instances in all the models of the XForms document (the standardinstance()
function only searches within the current XForms model).<xforms:model id="main-model"><xforms:instance id="main-instance">...</xforms:instance></xforms:model><xforms:model id="resources-model"><xforms:instance id="resources-instance">...</xforms:instance></xforms:model>...<xforms:group model="main-model"><xforms:output value="xxforms:instance('resources-instance')/titles/company-information"/></xforms:group> -
xxforms:index($repeat-id as xs:string?) as xs:integer
.The
xxforms:index()
function behaves like the standard XFormsindex()
function, except that its argument is optional. When the argument is omitted, the function returns the index of the closest enclosing<xforms:repeat>
element. This function must always be used within<xforms:repeat>
otherwise an error is raised.<xforms:repeat nodeset="employee" id="employee-repeat"><div><xforms:trigger><xforms:label>Add One</xforms:label><xforms:insert ev:event="DOMActivate" nodeset="../employee" at="xxforms:index()"/></xforms:trigger></div></xforms:repeat>
2.4.3. eXForms Functions
eXForms is a suggested set of extensions to XForms 1.0,
grouped into different modules. Orbeon Forms supports the exf:mip
module, which includes the
following functions:
-
exf:relevant()
-
exf:readonly()
-
exf:required()
Orbeon Forms also supports the following from the sorting module:
-
exf:sort()
eXForms functions live in the http://www.exforms.org/exf/1-0
namespace, usually
bound to the prefix exf
or exforms
.
2.5. JavaScript Integration
2.5.1. Rationale
While XForms gets you a long way towards creating a dynamic user-friendly user interface, there are some dynamic behaviors of the user interface that cannot be implemented easily or at all with XForms, or you might already have some JavaScript code that you would like to reused. A JavaScript API is provided to handle those cases, or other use cases involving JavaScript that you might have.
2.5.2. Getting and Setting Controls Value
In JavaScript, you get the current value of an XForms control var value =
ORBEON.xforms.Document.getValue("myControl")
where myControl
is the id of
the XForms control, for instance: <xforms:input id="myControl">
.
You set the value of an XForms control with ORBEON.xforms.Document.setValue("myControl",
"42")
where myControl
is the id of the XForms control, and 42
the new value. Setting the value with JavaScript is equivalent to changing the value of the
control in the browser. This will trigger the recalculation of the instances, and the dispatch
of the xforms-value-changed
event. More formally, the Value Change sequence of
events occurs.
As an example, consider you have the model below. It declares an instance with two elements
foo
and bar
, where bar
is a copy of foo
,
implemented with a calculate
MIP.
The input control below is bound to foo
, and the output control is bound to
bar
. When activated, the trigger executes JavaScript with the
<xxforms:script>
action. It increments the value of the input control bound to
foo
. When this happens the value displayed by the output control bound to
bar
is incremented as well, as bar
is a copy of foo
.
2.5.3. Dispatching Events
You can dispatch your own events from JavaScript by calling the function
ORBEON.xforms.Document.dispatchEvent()
. The parameters to this function are:
targetId | Mandatory |
Id of the target element. The element must be an element in the XForms namespace: you
cannot dispatch events to HTML elements. In addition, the id must identify either a
relevant and non-readonly XForms control, or a model object that supports event handlers
such as <xforms:model> , <xforms:instance> , or
<xforms:submission> .
|
---|---|---|
eventName | Mandatory |
Name of the event. Warning
For security reasons, by default Orbeon Forms prohibits client-side JavaScript
from dispatching any external events except <xforms:model xxforms:external-events="acme-super-event acme-famous-event">...</xforms:model>
This attribute contains a space-separated list of event name. In this example,
you explicitly enable your JavaScript code to fire the two events
Since the event handlers for custom events can be called by JavaScript code that runs on the client, you need to be aware that these handlers can potentially be activated by anybody able to load the form in his browser. |
form | Optional |
The form object that corresponds to the XForms form you want to dispatch the event to.
This argument is only needed when you have multiple "XForms forms" on the same HTML
page. Typically, this would only happens if you are running your form in a portal and
you have multiple portlets using XForms on the same page. When the parameter is not
present or null , the first form on the HTML page with the class
xforms-form is used.
|
bubbles | Optional | Optional boolean indicating if this event bubbles, as defined in DOM2 Events. The default value depends on the definition of the custom event. |
cancelable | Optional | Optional boolean indicating if this event bubbles, as defined in DOM2 Events. The default value depends on the definition of the custom event. |
incremental | Optional |
When false the event is sent to the XForms server right away. When
true the event is sent after a small delay, giving the opportinuty for other
events that would occur during that timespan to be aggregated with the current event.
|
ignoreErrors | Optional |
When set to true , errors happening while the event is dispatched to the
server are ignored. This is in particular useful when you are using a JavaScript timer
(e.g. window.setInterval() ) that runs a JavaScript function on a regular
interval to dispatch an event to the server, maybe to have part of the UI updated. In
some cases, you might not want to alert the user when a there is a maybe temporary
communication error while the event is being dispatched to the server. In those cases,
you call call dispatchEvent with ignoreErrors set to true.
|
In most cases, you only need to call dispatchEvent()
with a target id and event name,
as in:
ORBEON.xforms.Document.dispatchEvent("main-model", "do-something");
An event handler for the custom event can be in an XForms model or control, and can execute any
valid XForms action. Here an action is explicatly declared to handle the
do-something
even on the XForms model:
2.6. Attribute Value Templates
Certain attributes in XForms are literal values defined by the form author at the time the form is
written, as opposed to being evaluated at runtime. Examples include the action
attribute on <xforms:submission>
, or the resource
attribute on
<xforms:load>
.
To improve this, Orbeon Form supports a notation called Attribute Value Templates (AVTs),
borrowed from XSLT, which allows including XPath expressions within attributes. You include XPath
expressions in attributes by enclosing them within curly brackets ({
and
}
). Consider this example:
When <xforms:load>
is executed, the resource
attribute is evaluated.
The results is the concatenation of /forms/detail/
and of the result of the expression
within brackets
instance('documents-instance')/documents/document[index('documents-repeat')]/id
. If the
id
element pointed to contains the string
C728595E0E43A8BF50D8DED9F196A582
, the resource
attribute takes the
value /forms/detail/C728595E0E43A8BF50D8DED9F196A582
.
AVTs are currently supported only within certain attributes:
-
<xforms:submission>
:action
,xxforms:username
,xxforms:password
,xxforms:readonly
andxxforms:shared
attributes. -
<xforms:dispatch>
:name
attribute. -
<xforms:load>
:resource
attribute. -
<xforms:setfocus>
:control
attribute.
There are plans to support AVTs in more places in the future.
2.7. Dialogs
2.7.1. The xxforms:dialog Control
You declare dialogs directly under the <xhtml:body>
element with:
-
When you have
appearance="full"
on the dialog, you define the title of the dialog with the embedded<xforms:label>
element. -
Inside an
<xxforms:dialog>
you can use all the XHTML and XForms elements you can normally use elsewhere on the page. You can have other XForms controls, or show anything you would like to with HTML. -
The attributes on the
<xxforms:dialog>
are as follows:
id | Mandatory |
The ID of the dialog. You reference this ID when opening the dialog with
<xxforms:show dialog="my-dialog-id"> .
|
---|---|---|
appearance |
Optional. Possible values are:
|
You can set the appearance to either full or minimal :
|
level |
Optional. Can only be used appearance is set to full . Possible values are:
|
When set to modal the rest the page is grayed out and you can't interact
with any ontrol on the page outside of the dialog. When set to modeless you
can still use other controls on the page.
|
close |
Optional. Can only be used appearance is set to full . Possible values are:
|
A "x" is shown in the dialog title bar when close is set to
true . If you specify close="false" , then you should provide a
way to close the dialog, for instance by having you own "Close" button inside the
dialog. This is typically useful when you want to force users to enter some data before
proceeding and you don't want them to cancel the current operation by closing the
dialog.
|
draggable |
Optional. Can only be used appearance is set to full . Possible values are:
|
When set to false , you won't be able to move dialog on the page by using
drag and drop in the dialog title bar.
|
2.7.2. The xxforms:show and xxforms:hide Actions
[To be completed]
2.7.3. The xxforms-dialog-open and xxforms-dialog-close Events
[To be completed]
2.8. Other Extensions
2.8.1. XForms Submission - HTTP Authentication
The xforms:submission
element supports optional xxforms:username
and
xxforms:password
attributes that allow specifying HTTP authentication credentials.
You can specify either both attributes, or only the xxforms:username
attribute. The
latter case is equivalent to setting the value of xxforms:password
to an empty
string.
2.8.2. XForms Submission/Load - Loading Indicator
When an xforms:submission
with replace="all"
is executed, in general,
the browser will load another page. While this happens, the loading indicator, by default shown
in red at the top right of the window, is displayed. However, when the browser is served not a
web page but say a ZIP file, the browser might ask you in you want to download it, and then stay
in the current page. When this happens, the loading indicator does not go away.
In those cases where you know that the target page does not replace the current page, you can
prevent the loading indicator from being displayed by adding the
xxforms:show-progress="false"
attribute:
Similarly the xxforms:show-progress="false"
attribute can be used with the
xforms:load
action:
2.8.3. XForms Submission/Load - Target
You can use the xxforms:target
attribute on both xforms:submission
and
xforms:load
. It behaves just like the HTML target attribute.
When used on xforms:submission
, it makes sense to use this attribute only when you
have a replace="all"
, as the replace="instance"
doesn't load another
page.
2.8.4. xxforms:script Action
The xxforms:script
action allows you to call client-side JavaScript as a result of
XForms events:
xxforms:script
actions are currently always executed last in a sequence
of XForms actions, even if they appear before other XForms actions.
2.8.5. Read-Only XForms Instances with xxforms:readonly
Orbeon Forms supports an extension attribute, xxforms:readonly
, on the
<xforms:instance>
and <xforms:submission>
elements. When set to
true
, this attribute signals that once loaded, the instance is read-only, with the
following consequences:
-
The instance is loaded into a smaller, more efficient, read-only data structure in memory.
-
Instance values cannot be updated, and no Model Item Properties (MIPs) can be assigned with
<xforms:bind>
to the instance. But a read-only instance can be replaced entirely by an<xforms:submission replace="instance">
-
When using client-side state handling, less data may be transmitted between server and client.
Read-only instances are particularly appropriate for loading internationalization resources, which can be large but don't change. Example:
The xxforms:readonly
attribute on <xxforms:instance>
determines if
the instance is read-only until that instance is being replaced. After an instance is replaced,
it can be read-only or not irrelevant of the of xxforms:readonly
on
<xxforms:instance>
. When the instance is replaced, the replaced instance is
read-only if and only if the <xforms:submission>
that does the replacement has a
attribute xxforms:readonly="true"
.
2.8.6. Sharing of Read-Only XForms Instances with xxforms:shared
Orbeon Forms supports an extension attribute, xxforms:shared
, on the
<xforms:instance>
and <xforms:submission>
elements. This
attribute can be used only when an XForms instance is marked as read-only with
xxforms:readonly="true"
. xxforms:shared
can take two values:
document
(the default if the attribute is not specified) and
application
. When application
is specified:
-
The instance can be shared at the application level identified just by its source URL.
-
The instance is not stored into the XForms document's state, but in a global cache, therefore potentially saving memory. If, upon loading an XForms document, the instance is found in the cache, it is directly retrieved from the cache. This can save time especially if the URL can take significant time to load.
-
The URL must refer to a constant XML document and authorization credentials such as username and password should not cause different data to be loaded.
Here is how you use the attribute on <xforms:instance>
:
When used on <xforms:submission>
, the submission has to use
method="get"
method and replace="instance"
:
You set the size of the shared instances cache using a property in properties.xml
:
You can force the XForms engine to remove a shared instance from the cache by dispatching the
xxforms-instance-invalidate
event to it. The next time an XForms document requires
this instance, it will not be found in the cache and therefore reloaded. Example:
When using xxforms:readonly="true"
, another attribute, xxforms:ttl
,
can be used to set a time to live for the instance in cache. This duration is expressed
in milliseconds and has to be greater than zero. When a shared instance if found in cache but
has an associated time to live, if it was put in the cache more than time to live milliseconds
in the past, then the instance is discarded from the cache and retrieved again by URI as if it
had not been found in cache at all. The following example expires the shared instance after one
hour:
xxforms:shared="application"
, be sure that the data contained in the
instance does not contain information that could be inadvertently shared with other XForms
documents. It is recommended to use it to load localized resources or similar types of data.
2.8.7. Controlling Item Sets Refreshes with xxforms:refresh-items
XForms specifies that items and itemsets are re-evaluated when processing
xforms-refresh
. This may happen quite often, and may lead to time-consuming
re-evaluations especially when there are many or large itemsets.
Orbeon Forms supports an extension attribute, xxforms:refresh-items
, on the
<xforms:select>
and <xforms:select1>
elements. When set to
true
(the default), items and itemsets are re-computed upon
xforms-refresh
event processing. When set to false
, this attribute
signals that once computed, the set of items for the control will not be recomputed upon
xforms-refresh
event processing.
If you know that itemsets do not change over time, setting xxforms:refresh-items
to
false
disables refreshing of the items during xforms-refresh
and may
yield significant performance improvements. For example:
2.8.8. Trees with the xxforms:tree Appearance
[TODO: describe the Orbeon Forms xxforms:tree
appearance on
xforms:select
and xforms:select1
]
2.8.9. Menus with the xxforms:menu Appearance
[TODO: describe the Orbeon Forms xxforms:tree
appearance on
xforms:select1
]
3. Configuration
3.1. State Handling
3.1.1. Rationale
The Orbeon Forms XForms engine requires keeping processing state while operating on an XForms page. Such state includes the current values of XForms instances, selected repeated elements, and more. With Orbeon Forms, XForms state information can be handled in one of two ways:
-
Server-side: in this case, state information is stored on the server. Only very little state information circulates between client and server. The most frequently used state information is stored in memory. Less frequently used state information is stored on disk in a local database.
Benefits of the approach:
-
Resulting HTML page are smaller. HTML pages increase in size as more XForms controls are used, but they don't increase in size proportionally to the size of XForms instances.
-
Small amounts of data circulate between the client browser and the Orbeon Forms XForms server.
-
This means that very large XForms instances can be processed without any impact on the amount of data that is transmitted between the client and the server.
Drawbacks of the approach:
-
The Orbeon Forms XForms server needs to be stateful. It uses server memory to store state information even when no request is being processed. This creates additional demand for resources on the server and slightly complicates the task of tuning the server.
-
State information can become unavailable when sessions expire or when the server is restarted. When state information becomes unavailable for a page, that page will no longer function unless it is reloaded.
NoteOrbeon Forms ensures that it is possible to open multiple client browser windows showing the same page within the same session. -
-
Client-side: in this case, static initial state information is sent along with the initial HTML page, and dynamic state is exchanged over the wire between the client browser and the Orbeon Forms XForms server when necessary.
Benefits of the approach:
-
The Orbeon Forms server is entirely stateless. It only requires memory while processing a client request. It can be restarted without consequence for the XForms engine.
-
State information does not expire as long as the user keeps the application page open in the web browser.
Drawbacks of the approach:
-
Resulting HTML pages are larger. In particular, the size of state data grows when XForms instances grow, regardless of whether many XForms controls are bound to instance data.
-
More data circulates between the client browser and the Orbeon Forms XForms server.
NoteOrbeon Forms compresses and encrypts XForms state information sent to the client. -
By default, Orbeon forms store XForms state information on the server. Please change this default to client-side only if you have well understood the tradeoffs explained above.
3.1.2. Configuring State Handling
State handling can be configured globally for all pages, or locally for each individual page
served. Global configuration is performed in properties.xml
with the
oxf.xforms.state-handling
property. When missing or set to client
,
state is stored client-side. When set to server
, state is stored server-side. For
example:
The global configuration can be overridden for each page by setting the
xxforms:state-handling
attribute in the page. This attribute can be set on the
root element of the XHTML page, or on the first xforms:model
element. Only the
first such attribute encountered by the XForms engine is used:
When storing state on the server, the maximum size of the data to be stored globally in memory
can be selected using the oxf.xforms.store.application.size
property. The size is
specified in bytes:
When the allowed memory space for state information is full, Orbeon passivates state information to a local eXist database. Configuration parameters for the connection to the eXist database can be changed. The defaults are as follows:
Whether state information is kept client-side or server-side, a property controls whether the XForms
engine should try to optimize state reconstruction by using a cache. This property should usually
be set to true
:
If the above property is set to true
, the number of XForms documents that can be
held in that document cache at a given time is configured with the following property:
Note that this represents XForms documents in a particular state of interaction with a user, which means that if to users load the same XForms page two entries will be needed in the cache.
3.2. JavaScript and CSS Resources
3.2.1. Minimal Resources
Most JavaScript and CSS files used by the XForms engine are available in two versions:
-
A full version, which may contain comments, spaces, longer identifiers, etc.
-
A minimal version, which is usually much smaller
Both versions work exactly the same. For development and debugging of the XForms engine itself, the full
version is easier to work with. But if you never work directly with these JavaScript and CSS files, as
well as for deployment, the minimal versions are recommended as they will load faster in the user's web
browser. You enable minimal resources in properties.xml
as follows:
3.2.2. Combined Resources
Serving CSS and JavaScript can have a high performance cost on page loads. This is particularly important with the intensive use of JavaScript in Orbeon Forms. In particular, it can be shown that serving many small files is slower than serving a single large file. In theory, HTTP pipelining can improve very much on this, but this is (very unfortunately) useless in practice at the time of writing because Internet Explorer doesn't implement it at all and Firefox / Mozilla do implemente it but do not enable it by default. This is why Orbeon Forms supports the option of combining the multiple JavaScript and CSS files required for a given XForms page into a single JavaScript file and a single CSS file.
You enable this feature in properties.xml
as follows
When this is enabled, Orbeon Forms refers to a single JavaScript file and a single CSS file for XForms-related functionality. The URL identifies special resources needed by the page, for example:
This in short tells the XForms server to produce the minimal CSS and JavaScript for the XForms engine including support for the "range" and "autocomplete" features. Note that you don't have to write these URLs yourself: the Orbeon Forms XForms engine adds them automatically to your page.
When the Orbeon Forms XForms server receives a request for a combined resource, it determine what files
need to be combined and outputs them all together. Furthmore, for CSS files, all URLs referred to with
url()
are rewritten, so that links to images, in particular, remain correct.
In addition, you can enable caching of combined resources with:
This cache works differently from other Orbeon Forms caches, as the result is stored in the resources, typically under:
One benefit of this mechanism is that it allows making such combined files to be served by an Apache front-end.
3.3. Debugging XForms Pages
3.3.1. Enabling XForms Logging
When a fatal error occurs, the XForms engine throws a Java exception which either results in an error
page in your web browser (when the error occurrs during page initialization) or in an error message at
the top of the displayed XForms page (when the error occurs during an Ajax request after the page is
loaded). The main Java exception is also logged on the server. Often, this provides enough information
to the developer to figure out what went wrong. When this is not sufficient, the best tool available is
the XForms engine logging facility. To enable it, make sure you uncomment the following lines in
config/log4j.xml
:
You must restart your Servlet container for those changes to be taken into account.
This setting enables verbose logging of the XForms engine's operations, in particular:
-
Dispatching of events.
-
Execution of actions.
-
Loading of instances.
-
Execution of submissions.
-
Resulting XForms instances.
-
XForms cache-related operations.
The following figure shows a sample XForms logging session in Orbeon Studio:
3.3.2. The Instance Inspector
The Instance Inspector allows you to visualize all the instances of your XForms page. You enable it by adding the following within your XForms page:
This is an example of how the Instance Inspector looks like in your page:
You can select which model and instand to view, and decide whether to see plain XML or formatted XML.
4. Migrating from XForms Classic to XForms NG
Migrating from XForms Classic to XForms NG consists in telling Orbeon Forms to use XForms NG, in making the necessary changes to adjust your XForms model and controls (this is necessary as XForms Classic was lacking in terms of compatibility with the XForms specification, and XForms NG on the contrary aims at implementing XForms 1.0 and XForms 1.1 fully), and (sometimes optionally) in making some architectural changes to your application:
-
Configuring Orbeon Forms to use XForms NG.
-
Identify in your page flow the pages that use XForms Classic. Those are defined by
<page>
elements with thexforms
attribute, for example:<page id="my-page" path-info="/my/page" xforms="/my-page/xforms-model.xml" view="/my-page/view.xhtml"/> -
For each page identified in the previous step, locate the XForms model file referred by the
xforms
attribute. In most cases, this is a static XML file with a root element called<xforms:model>
, for example:<xforms:model><xforms:instance>...</xforms:instance>...</xforms:model>You must now insert the content of that file into your XHTML page view. In most cases, the page view is a static XHTML file or a dynamic XSLT file that produces XHTML. Locate the
<xhtml:head>
element and insert the XForms model as a child of that element:<xhtml:html><xhtml:head><xhtml:title>My Page</xhtml:title><xforms:model><xforms:instance>...</xforms:instance>...</xforms:model></xhtml:head><xhtml:body>...</xhtml:body></xhtml:html>Alternatively, you can use XInclude to keep the XForms model external:
<xhtml:html><xhtml:head><xhtml:title>My Page</xhtml:title><xi:include href="oxf:/my-page/xforms-model.xml"/></xhtml:head><xhtml:body>...</xhtml:body></xhtml:html> -
In the page flow, remove the
xforms
attribute on the<page>
element:<page id="my-page" path-info="/my/page" view="/my-page/view.xhtml"/>What you have achieved at this point is migrating from XForms Classic's external XForms model specification to the up-to-date way of including XForms directly within XHTML. Note that this also allows you to use multiple XForms models simply by adding them as children of the
<xhtml:head>
element:<xhtml:html><xhtml:head><xhtml:title>My Page</xhtml:title><xforms:model id="main-model">...</xforms:model><xforms:model id="resources-model">...</xforms:model></xhtml:head><xhtml:body>...</xhtml:body></xhtml:html>
-
-
Updating XForms model and controls.
You are very likely to have to make further adjustments to your XForms controls and model. The following are possible things to look at:
-
The
<xforms:submit>
control requires asubmission
attribute referring to an existing<xforms:submission>
element within an XForms model. Start creating an<xforms:submission>
element, assign it an id, and then set thesubmission
attribute on<xforms:submit>
. For example:<xforms:submission id="default-submission" method="post" action="/services/save" replace="none"/>...<xforms:submit submission="default-submission"><xforms:label>Save</xforms:label></xforms:submit> -
The
<xxforms:if>
and<xxforms:choose>
extensions no longer work with XForms NG. Use<xforms:switch>
or<xforms:group>
with relevance instead. Note that you can often convert simply from:<xxforms:if test="/form/first-name = 'Joe'">...</xxforms:if>to:
<xforms:group ref=".[/form/first-name = 'Joe']">...</xforms:group> -
With XForms Classic, activacting a trigger would make the unique XForms instance of the unique XForms model available to Page Flow Controller processing (i.e. a PFC action, model and view could be activated). With NG, this is no longer the case and processing follows the XForms specification. This means in particular that if a submission fails because the submitted instance is invalid, that instance will never be sent by the XForms engine and will not, in particular, reach a page or service declared in the page flow (unless the XForms 1.1
validate="false"
attribute on<xforms:submission>
is set).Similarly, using triggers to perform insertions or deletions into XForms instances does not cause a submission to happen with XForms NG.
-
With XForms Classic, a submission would annotate an XForms instance with attributes such as
xxforms:valid="true"
, etc. This is no longer the case with XForms NG.
-
-
Architectural considerations.
-
Much of the work that was performed with page flow actions with XForms Classic can be implemented with XForms events and XForms actions. This means that you will tend to migrate functionality away from the PFC and towards XForms. This also means that you will use less XSLT to produce your pages, or even none at all, which is ideal as that is one less technology tha developers have to learn.
-
Because of the power of the
<xforms:submission>
element (which, with XForms 1.1, allows you to call any REST service), you are likely to move towards a service-oriented approach where your XForms page uses submissions that communicate with services. Such services may be external, or they may be implemented in Orbeon Forms and mapped in your page flow.
-