UI refresh events
We call refresh events the following UI events defined in XForms, as they can occur during UI refresh:
xforms-value-changed
xforms-enabled
/xforms-disabled
xforms-readwrite
/xforms-readonly
xforms-optional
/xforms-required
xforms-valid
/xforms-invalid
There are other UI events that are dispatched outside of refresh, including
DOMActivate
, xforms-select
, etc. These are not considered here.Refresh events allow:
- reliably tracking a control's MIP status during its lifecycle
- reliably tracking changes to the control's value as seen by the control/user
We make a distinction between:
- XForms markup designed to represent a control, such as
<xf:input>
. - concrete controls in the sense of runtime objects able to keep state.
XForms markup for controls may or may not yield the creation of concrete controls, depending on repeats and relevance conditions.
A concrete control has a simple lifecycle:
- It is created.
- While in existence, it might keep and modify state information.
- It may be destroyed.
After being destroyed:
- A concrete control is considered non-existent.
- Therefore it does not keep or modify internal state.
A control is concrete if it meets the conditions for relevance:
- It has no binding attribute and is at the top-level or within a relevant container control
- It has a binding attribute
- AND it is at the top-level OR within a relevant container control
- AND the binding attribute resolves to a non-empty node-set
- AND
- for single-node bindings, the first node of the binding has the relevant property
- for items-set bindings, at least one node of the binding has the relevant property
Concrete controls are created at the following times:
- during processing of the default action for
xforms-model-construct-done
event, if they meet the conditions for relevance - when a new repeat iteration is inserted into a repeat container, if they meet the conditions for relevance
- either during
xf:insert
processing - or during refresh
- during refresh, when the condition for relevance goes from non-relevant to relevant
Concrete controls are destroyed at the following times:
- when a repeat iteration is removed from a repeat container
- or during refresh
- during refresh, when the condition for relevance goes from relevant to non-relevant
NOTE: If the binding of a control changes from one node to another during refresh, the control is not destroyed.
Controls maintain their own state, including value and MIP state.
Just after a control becomes relevant, whether during:
- initial UI creation
- creation of a new repeat iteration
- subsequent change from non-relevant to relevant due to node bindings, MIPs, or enclosing control relevance during refresh
The following occurs:
- The control's state, including value and MIPs, is acquired through its binding and other attributes.
xforms-enabled
is dispatchedxxforms-visible
is dispatched if the control is not in a hidden switch case- SINCE Orbeon Forms 2018.1
- non-default MIP events are dispatched (in order to reduce the number of events dispatched)
xforms-invalid
xforms-required
xforms-readonly
NOTE: a good rationale can be made for not dispatching non-default MIP events:
- If they are considered change events, then they should behave like
xforms-value-changed
. - Context information upon
xforms-enabled
can be used to determine the initial state of the MIPs.
NOTE:
xforms-value-changed
is NOT dispatched (because there is no "value change").Just before a control becomes non-relevant, whether during:
- destruction of a repeat iteration
- subsequent change from relevant to non-relevant due to node bindings, MIPs, or enclosing control relevance during refresh
The following occurs:
xxforms-hidden
is dispatched if the control is not in a hidden switch case- SINCE Orbeon Forms 2018.1
xforms-disabled
is dispatched- no other events are dispatched
Each relevant control stores its current value and MIP information. Therefore refresh events are related directly to controls, and no longer to instance data nodes. This is an important difference with XForms 1.1.
While the control is relevant, upon refresh:
- Its current MIP and value are stored temporarily as the control's old state.
- The new control state, including value and MIPs, is acquired through its binding and other attributes.
- Old and new state are compared.
- Events related to value and MIP changes are dispatched.
NOTES:
xf:output/@value
also dispatchesxforms-value-changed
.xf:var
also dispatchxforms-value-changed
.
NOTE: XForms 1.1 says that all MIP events must be dispatched upon value change. This is not not necessary because those events are properly tracked independently.
Refresh events in XForms 1.1 are based on:
- marking instance data nodes as their value change or binds apply to them
- checking those markings during refresh
- dispatching events based on that check
This mechanism is not satisfying because we think that it goes against the expectations of the form author and it does not produce events reliably (see email sent to public-forms mailing-list on June 12, 2007). Therefore Orbeon Forms does not strictly follow XForms 1.1 on this topic.