UI refresh events

Introduction

What are 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.

Purpose of refresh events

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

Lifecycle of a control

Markup and concrete controls

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

    • either during xf:delete processing [UNTIL Orbeon Forms 2017.2 included, see #3503]

    • 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 state

Controls maintain their own state, including value and MIP state.

Control creation

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 dispatched

  • xxforms-visible is dispatched if the control is not in a hidden switch case

  • 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").

Control destruction

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

  • xforms-disabled is dispatched

  • no other events are dispatched

Changes during the lifetime of the control

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 dispatches xforms-value-changed.

  • xf:var also dispatch xforms-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.

Compatibility note: UI refresh events in XForms 1.1

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.

See also

Last updated