Relevance
The concept of "relevance" for a control relates to whether the control is "active" in the UI. A non-relevant control is typically not shown at all. We propose the following notions:
- A relevant control concretely exists, in that it has a run-time object representing the UI control and its state, associated with its template in the markup.
- A non-relevant control does not exist. Only a template for it exists in the markup.
- A control goes from non-extant to extant by a process of creation.
- A control goes from extant to non-extant by a process of destruction.
In XForms 1.1, the notions above are already supported by the language related to the creation and destruction of repeat iterations, although they are absent from other parts of the spec.
XForms 1.0/1.1 only discusses creation/destruction (relevance changes) after the initial UI has been initialized. However they can happen in these situations:
- Creation
- Initial UI creation
- Creation of a new repeat iteration (which as per XForms 1.1 is performed in the same way as initial UI creation)
- Subsequent change from non-relevant to relevant due to node bindings, MIPs, or enclosing control relevance during refresh
- Destruction
- Destruction of a repeat iteration
- Subsequent change from relevant to non-relevant due to node bindings, MIPs, or enclosing control relevance during refresh
There are two ways of addressing the cases not covered by XForms 1.1:
- Use xforms-enabled/xforms-disabled
- Use new events
For simplicity and consistency reasons, we choose option #1 and dispatch
xforms-enabled/
xforms-disabled in all the cases above.
Rules:
- Every control receives xforms-enabled after being created (becoming relevant).
- Every control receives xforms-disabled before being destroyed (becoming non-relevant).
- While a control is relevant, it can get refresh events updates for the other refresh events (more on this below).
Repeat handling
In XForms 1.1, repeat processing is pretty well defined.
- For each repeat iteration, a "repeat object" (implicit group) is created, containing the "run-time objects" representing the UI controls for that iteration
- "the user interface form controls generated for the repeat object are
initialized in the same manner as the user interface initialization
that is performed during default processsing of
xforms-model-construct-done"
This means that user interface controls can be updated in these circumstances:
- During UI initialization
- During refresh
- Just after the update of a repeat's node-set (through xforms:insert/xforms:delete) [TODO: does spec imply that value changes and instance replacements must update repeats immediately as well?]
An important question is whether refresh events must be dispatched after repeat node-set update, or only during refresh.
For
xforms-disabled, there is an issue: if the controls are removed from the UI just after an
xforms:delete, then it is not possible to dispatch
xforms-disabled events during a subsequent refresh because at that time, the controls will have disappeared already, and it is not possible to dispatch an event to a non-existing (non-relevant) control. So the only solution seems to be to dispatch
xforms-disabled just before the controls are removed from the UI.
What about control creation? Could dispatching of events be deferred until a subsequent refresh? That could be possible except for the following problem: a control becomes relevant in a new iteration, then the iteration is removed before the subsequent refresh. In that case, the control would get
xforms-disabled without ever getting
xforms-enabled. So it seems that here again,
xforms-enabled must be dispatched just after the creation of the new repeat iteration.
Rules:
- After the creation of new repeat iterations (as a result of xforms:insert), refresh events are dispatched for the newly created controls.
- Just before destruction of repeat iterations (as a result of xforms:delete), refresh events are dispatched for the controls to be destroyed.
Proposal
Lifecycle of a control
We make a distinction between:
- XForms markup designed to represent a control, such as <xforms: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 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
NOTE: This proposal equates existence, relevance, and visibility. As of 2010-10, the XForms working group is discussing whether some of these concepts should be separated.
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 node-set has the relevant property
- for node-set bindings, at least one node of the node-set 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 xforms:insert processing
- or during refresh
- During refresh, when the condition for relevance goes from non-relevant to relevant
Concrete controls as destroyed at the following times:
- When a repeat iteration is removed from a repeat container
- either during xforms:insert processing
- 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.
[TODO: document instance replacement]
[TODO: document predicates changed]
[TODO: document unbound controls (e.g. trigger, group w/o ref)]
Controls state
Controls maintain their own state, including value and MIP state. In the case of relevance the UI relevance is kept.
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:
- xforms-enabled is dispatched
- 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 these
- 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
- xforms-value-changed is NOT dispatched (in particular because there is no actual "value change")
- NOTE: We should add context information to all these events to provide access to
- value
- MIPs
- Q: what happens just before the control becomes non-relevant?
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:
- 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 as the control's old state
- the control is reevaluated, thus creating its new state
- old and new state are compared
- events related to MIP changes are dispatched
- xforms-value-changed is dispatched if the control's value has changed
- NOTES:
- xforms:output/@value also dispatches xforms-value-changed. This is possible since the control is able to store its previous value (XForms 1.1 does not support this).
- xxforms:variable should dispatch xforms-value-changed as well. [NOTE: This is not implemented in Orbeon Forms yet.]
- Closed selection controls should dispatch value changes based on values allowed in their itemsets. [NOTE: This is not implemented in Orbeon Forms yet.]
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. Therefore this is entirely dropped from this proposal.
Open questions
Handling of relevance events for non-single-node binding controls
Relevance is a property which can apply to any XForms control, not only controls with a single-node binding. But is there any concrete case where this would apply currently:
- xforms:repeat
- thought: handling at level of individual iterations is probably better and would also allow detecting the insertion of new iterations (xforms-enabled)
- could complete this with new event xxforms-iteration-moved
- xxforms:dialog
- thought: wait until standard xforms:dialog is better formalized by XForms WG, in the meanwhile we do not need relevance
- xforms:case (not really a control!)
- already gets xforms-selected
- component
- thought: if we keep thinking of it as a non-XForms-specific construct, then it should not get xforms-enabled/disabled
Alerts attached to data nodes by constraints
[TODO]