9 XForms User Interface

This chapter covers XForms features for combining form controls into user interfaces.

9.1 The XForms Group Module

All form controls defined in 8 Form Controls are treated as individual units for purposes of visual layout e.g., in XHTML processing. Aggregation of form controls with markup defined in this chapter provides semantics about the relationship among user interface controls; such knowledge can be useful in delivering a coherent UI to small devices. For example, if the user interface needs to be split up over several screens, controls appearing inside the same aggregation would typically be rendered on the same screen or page. The elements and attributes included in this module are:

Element Attributes Minimal Content Model
group Common, UI Common, Single Node Binding label?, ((Form Controls)|group|switch|repeat)*

9.1.1 The group Element

The group element is used as a container for defining a hierarchy of form controls. Groups can be nested to create complex hierarchies.

Common Attributes: Common, UI Common , Single Node Binding

Note:

The binding expression is solely for the purpose of authoring convenience; it allows controls appearing within element group to use relative XPath expressions. Model item properties such as relevant on the bound instance node have no special effect on the group.

The label element has special significance when it appears as the first element child of group, representing a label for the entire group.

Example:

Example: Grouping Related Controls
<group ref="address">
  <label>Shipping Address</label>
  <input ref="line_1">
    <label>Address line 1</label>
  </input>
  <input ref="line_2">
    <label>Address line 2</label>
  </input>
  <input ref="postcode">
    <label>Postcode</label>
  </input>
</group>

The hierarchy defined by nested group elements is used to determine the traversal order specified by attribute navindex on form controls. Setting the input focus on a group results in the focus being set to the first form control in the navigation order within that group.

9.2 The XForms Switch Module

This section defines a switch construct that allows the creation of user interfaces where the user interface can be varied based on user actions and events. The elements and attributes included in this module are:

Element Attributes Minimal Content Model
switch Common, UI Common, Single Node Binding case+
case Common, selected (xsd:boolean) label?, ((Form Controls)|group|switch|repeat)*
toggle Common, case (xsd:IDREF) EMPTY

9.2.1 The switch Element

This element contains one or more case elements, any one of which is rendered at a given time.

Note:

This is separate from XForms relevant processing (see 6.1.4 The relevant Property), which is based on the current state of the XForms Model. As an example, portions of a questionnaire pertaining to the user's automobile may become relevant only if the user has answered in the affirmative to the question 'Do you own a car?'.

Common Attributes: Common, UI Common, Single Node Binding

Example:

Example: switch
<switch>
  <case id="in" selected="true">
    <input ref="yourname">
      <label>Please tell me your name</label>
      <toggle ev:event="xforms-activate" case="out"/>
    </input>
  </case>
  <case id="out" selected="false">
    <html:p>Hello <output ref="yourname" />.
      <trigger id="editButton">
        <label>Edit</label>>
        <toggle ev:event="xforms-activate" case="in"/>
      </trigger>
    </html:p>
  </case>
</switch>

The above results in the portion of the user interface contained in the first case being displayed initially. This prompts for the user's name; filling in a value and activating the control e.g., by pressing enter results switches to the alternate case, with a read-only output rendering. Activating the trigger labeled "Edit" in turn switches back to the original case.

9.2.2 The case Element

This element encloses markup to be conditionally rendered. The attribute selected determines the selected state and can be manipulated programmatically via the DOM, or declaratively via XForms action toggle.

Common Attributes: Common

Special Attributes:

selected

Optional selection status for the case. The default value is "false".

If multiple cases within a switch are marked as selected="true", the first selected case remains and all others are deselected. If none are selected, the first becomes selected.

9.2.3 The toggle Element

This XForms Action selects one possible case from an exclusive list of alternatives in a switch.

This action adjusts all selected attributes on the affected cases to reflect the new state, and then performs the following:

  1. Dispatching an xforms-deselect event to the currently selected case.

  2. Dispatching an xform-select event to the case to be selected.

Common Attributes: Common, Events

Special Attributes:

case

Required reference to a case section inside the conditional construct.

9.3 The XForms Repeat Module

The XForms Specification allows the definition of repeating structures such as multiple items within a purchase order. When defining the XForms Model, such higher-level collections are constructed out of basic building blocks; similarly, this section defines user interface construct repeat that can bind to data structures such as lists and collections. The elements and attributes included in this module are:

Element Attributes Minimal Content Model
repeat Common, UI Common, Node Set Binding, startindex (xsd:positiveInteger), number (xsd:nonNegativeInteger) ((Form Controls)|group|repeat)*
itemset Common, Node Set Binding label, (value|copy), (UI Common)*
copy Common, Single Node Binding EMPTY
insert Common, Events, Node Set Binding, at (XPathExpression), position ("before"|"after") EMPTY
delete Common, Events, Node Set Binding, at (XPathExpression) EMPTY
setindex Common, Events, repeat (xsd:IDREF), index (XPathExpression) EMPTY
(various) [repeat-nodeset, repeat-bind, repeat-model] (Node Set Binding attributes), repeat-startindex (xsd:positiveInteger), repeat-number (xsd:nonNegativeInteger) N/A

9.3.1 The repeat Element

This element defines a UI mapping over a homogeneous collection selected by Node Set Binding Attributes. This node-set must consist of contiguous child element nodes, with the same local name and namespace name of a common parent node. The behavior of element repeat with respect to non-homogeneous node-sets is undefined.

For example:

Example: Shopping Cart
<repeat nodeset="/cart/items/item">
  <input ref="." .../><html:br/>
</repeat>

Common Attributes: Common, UI Common, Node Set Binding

Special Attributes:

startindex

Optional 1-based hint to the XForms Processor as to which starting element from the collection to display. The default value is 1.

number

Optional hint to the XForms Processor as to how many elements from the collection to display. In the absence of this attribute, all elements of the collection are displayed.

This element operates over a homogeneous collection by binding the encapsulated user interface controls to each element of the collection. Attributes on this element specify how many members of the collection are presented to the user at any given time. XForms actions insert, delete, and setindex can be used to operate on the collection—see 10 XForms Actions. Another way to view repeat processing (disregarding special user interface interactions) is to consider "unrolling" the repeat. The above example is similar to the following (given four item elements in the returned node-set):

Example: Repeat Unrolled
<!-- unrolled repeat -->
  <input ref="/cart/items/item[1]" .../><html:br/>
  <input ref="/cart/items/item[2]" .../><html:br/>
  <input ref="/cart/items/item[3]" .../><html:br/>
  <input ref="/cart/items/item[4]" .../><html:br/>

Notice that the element node for the collection being populated would typically have defined model item properties minOccurs and maxOccurs; these values may in turn determine if the user agent displays appropriate UI controls for the user to add or delete entries in the collection.

Example: Homogeneous Collection
<model>
  <instance>
    <my:lines>
      <my:line name="a">
        <my:price>3.00</my:price>
      </my:line>
      <my:line name="b">
        <my:price>32.25</my:price>
      </my:line>
      <my:line name="c">
        <my:price>132.99</my:price>
      </my:line>
    </my:lines>
  </instance>
</model>
      ...
<repeat id="lineset" nodeset="/my:lines/my:line">
  <input ref="my:price">
    <label>Line Item</label>
  </input>
  <input ref="@name">
    <label>Name</label>
  </input>
</repeat>
<trigger>
  <label>Insert a new item after the current one</label>
  <action ev:event="xforms-activate">
    <insert nodeset="/my:lines/my:line" at="index('lineset')"
            position="after"/>
    <setvalue ref="/my:lines/my:line[index('lineset')]/@name"/>
    <setvalue ref="/my:lines/my:line[index('lineset')]/price">0.00</setvalue>
  </action>  
</trigger>
<trigger>
  <label>remove current item</label>
  <delete ev:event="activate" nodeset="/my:lines/my:line"
          at="index('lineset')"/>
</trigger>

9.3.2 Creating Repeating Structures Via Attributes

Element repeat enables the creation of user interfaces for populating repeating structures. When using XForms within host languages like XHTML, it is often necessary to create repeating structures within constructs such as table. Thus, one might wish to use element repeat within a table to create the rows of a table, where each row of the table binds to a distinct member of a homogeneous collection. Since html:table doesn't (and probably never will) allow xforms:repeat elements as children, another syntax is needed.

Example: Tables And Repeating Structures
<table>
  <repeat nodeset="...">
    <tr>
      <td>...</td>
      ...
    </tr>
  </repeat>
</table>

More generally, there is a need to integrate repeat behavior into host languages at points where the content model of the host language does not or cannot provide the appropriate extension hooks via modularization. To accommodate this, XForms 1.0 defines an alternative syntax that is functionally equivalent to the repeat element, using the following attributes:

repeat-model
repeat-bind
repeat-nodeset
repeat-startindex
repeat-number

The above attributes are equivalent to the repeat attributes of the same name, but without the prefix repeat-. A host language can include these attributes in the appropriate places to enable repeating constructs. For example, a version of XHTML might use:

Example: Tables And Repeating Structures
<html:table xforms:repeat-nodeset="...">
  <html:tr>
    <html:td><xforms:output ref="..."/></html:td>
  </html:tr>
</html:table>

Which could be validated against an appropriately configured XHTML Schema that includes the XForms Repeat module. Note that what gets repeated is the child elements of the element with the repeat- attributes.

This should be thought purely as a syntactic transformation, i.e., there is no change to repeat processing semantics. Further, for purposes of understanding the above as a pure syntactic transformation, element repeat can be viewed as containing an anonymous group that wraps the contents of element repeat. Thus, consider the following:

<repeat ...>
...
</repeat>

is equivalent to

<repeat ...>
  <group>...</group>
</repeat>

Which is equivalent to

<group repeat-...>
  ...
</group>

Additionally, when using XForms Action setindex, attribute repeat of type idref can point to any element carrying the repeat attributes. Similarly, when using function index against a repeating structure created via the repeat-attributes, the id of that element can be used as the argument to function index.

9.3.3 The itemset Element

This element allows the creation of dynamic selections within controls select and select1, where the available choices are determined at run-time. The node-set that holds the available choices is specified via attribute nodeset. As with repeat, this nodeset should refer to a homogeneous collection. Child elements label and value indirectly specify the label and storage values. Notice that the run-time effect of itemset is the same as using element choices to statically author the available choices.

Common Attributes: Common, Node Set Binding

Note:

Whenever a refresh event is dispatched the nodeset is re-evaluated to update the list of available choices.

The following example shows element itemset within control select to specify a dynamic list of ice cream flavors:

Example: Dynamic Choice Of Ice Cream Flavors
<model id="cone">
  <instance>
    <my:icecream>
      <my:order/>
    </my:icecream>
  </instance>
</model>
<model id="flavors">
  <instance>
    <my:flavors>
      <my:flavor type="v">
        <my:description>Vanilla</my:description>
      </my:flavor>
      <my:flavor type="s">
        <my:description>Strawberry</my:description>
      </my:flavor>
      <my:flavor type="c">
        <my:description>Chocolate</my:description>
      </my:flavor>
    </my:flavors>
  </instance>
</model>
<!-- user interaction markup -->
<select model="cone" ref="my:order">
  <label>Flavors</label>
  <itemset model="flavors" nodeset="/my:flavors/my:flavor">
    <label ref="my:description"/>
    <copy ref="my:description"/>
  </itemset>
</select>
<!-- For all three items selected, this example produces instance data like
<my:icecream>
  <my:order>
    <my:description>Vanilla</my:description>
    <my:description>Strawberry</my:description>
    <my:description>Chocolate</my:description>    
  </my:order>
</my:icecream>
-->

9.3.4 The copy Element

Structurally, this element is similar to 8.2.3 The value Element. It differs in that it can only be used within itemset, and that it works with subtrees of instance data rather than simple values.

Common Attributes: Common, Single Node Binding

When an item becomes selected, the following rules apply:

  • The target node, selected by the binding attributes on the list form control, must be an element node, otherwise an exception results (4.5.1 The xforms-binding-exception Event).

  • The element node associated with the item, selected by the binding attributes on copy, is deep copied as a child of the target node.

  • A full computational dependency rebuild.

When an item becomes unselected, the following rules apply:

  • The target node, selected by the binding attributes on the list form control, must be an element node, otherwise an exception results (4.5.1 The xforms-binding-exception Event).

  • The child element node associated with the item, selected by the binding attributes on copy, is deleted.

  • A full computational dependency rebuild.

9.3.5 The insert Element

This action is used to insert new entries into a homogeneous collection, e.g., a set of items in a shopping cart. Attributes of action insert specify the insertion in terms of the collection in which a new entry is to be inserted, and the location within that collection where the new node will appear. The new node is created by cloning the final member of the homogeneous collection specified by the initialization instance data. In this process, nodes of type xsd:ID are not copied.

Common Attributes: Common, Events, Node Set Binding

Special Attributes:

at

Required XPath expression evaluated to determine insert location.

position

Required selector ("before" or "after") of insert before/after behavior.

The rules for insert processing are as follows:

  1. The homogeneous collection to be updated is determined by evaluating binding attribute nodeset.

  2. The corresponding node-set of the initial instance data is located to determine the prototypical member of the collection. The final member of this collection is cloned to produce the node that will be inserted. Finally, this newly created node is inserted into the instance data at the location specified by attributes position and at.

    Attribute at is evaluated to determine the insertion index—a numerical value that is the index into the node-set. Attribute position specifies whether the new node is inserted before or after this index.

    The rules for selecting the index are as follows:

    1. The return value of the XPath expression in attribute at is processed according to the rules of the XPath function round(). For example, the literal 1.5 becomes 2, and the literal 'string' becomes NaN.

    2. If the result is NaN, the insert appends to the end of the node-set.

    3. If the resulting index is outside the valid range of the node-set, it is replaced with either 1 or the size of the node-set, whichever is closer.

  3. Finally, the index for any repeating sequence that is bound to the homogeneous collection where the node was added is updated to point to the newly added node. The indexes for inner nested repeat collections are re-initialized to 1.

This action results in the insertion of newly created data nodes into the XForms instance data. Such nodes are constructed as defined in the initialization section of the processing model—see 4.2 Initialization Events. As an example, this causes the instantiation of the necessary user interface for populating a new entry in the underlying collection when used in conjunction with repeating structures.

Note:

If this action is contained within an action element, it has special deferred update behavior (10.1.1 The action Element).

An example of using insert with a repeating structure is located at 9.3.1 The repeat Element. Note that XForms Action setvalue can be used in conjunction with insert to provide initial values for the newly inserted nodes.

9.3.6 The delete Element

This action deletes nodes from the instance data.

Common Attributes: Common, Events, Node Set Binding

Special Attributes:

at

Required XPath expression evaluated to determine delete location.

The rules for delete processing are as follows:

  1. The homogeneous collection to be updated is determined by evaluating binding attribute nodeset. If the collection is empty, the delete action has no effect.

  2. The n-th element node is deleted from the instance data, where n represents the number returned from node-set index evaluation, defined in 9.3.5 The insert Element. If no nth node exists, the operation has no effect.

  3. If the last remaining item in the collection is removed, the index position becomes 0. Otherwise, the index will point to the new n-th item.

This action results in deletion of nodes in the instance data.

Note:

If this action is contained within an action element, it has special deferred update behavior (10.1.1 The action Element).

An example of using delete with a repeating structure is located at 9.3.1 The repeat Element.

9.3.7 The setindex Element

This action marks a specific item as current in a repeating sequence (within 9.3.1 The repeat Element).

Common Attributes: Common, Events

Special Attributes:

repeat

Required reference to a repeating element.

index

Required XPath expression that evaluates to a 1-based offset into the sequence.

The implementation data structures for tracking computational dependencies are rebuilt or updated as a result of this action. The indexes for inner nested repeat collections are re-initialized to 1.

9.3.8 Repeat Processing

The markup contained within the body of element repeat specifies the user interface to be generated for each member of the underlying collection. During user interface initialization (see 4.2.4 The xforms-ui-initialize Event), the following steps are performed for repeat:

  1. Attribute nodeset is evaluated to locate the homogeneous collection to be operated on by this repeat.

  2. The corresponding nodes in element instance in the source document are located—these nodes provide initial values and also serve as a prototypical instance for constructing members of the repeating collection.

  3. The index for this repeating structure is initialized to point at the head of the collection.

  4. The user interface template specified within element repeat is bound to this prototypical instance. If there is a type mismatch between the prototypical instance and the binding restrictions for the user interface controls, an error is signaled and processing stops.

  5. User interface as specified by the repeat is generated for the requisite number of members of the collection as specified by attributes on element repeat, and model item constraints minOccurs and maxOccurs.

The processing model for repeating structures uses an index that points to the current item in the instance data. This repeat index is accessed via XForms function index 7.7.5 The index() Function and manipulated via XForms Action setindex 9.3.7 The setindex Element. This index is used as a reference point for insert and delete operations. Notice that the contained XForms form controls inside element repeat do not explicitly specify the index of the collection entry being populated. This is intentional; it keeps both authoring as well as the processing model simple.

The binding expression attached to the repeating sequence returns a node-set of the collection being populated, not an individual node. Within the body of element repeat, binding expressions are evaluated with a context node of the node determined by the index. Repeat processing uses XPath expressions to address the collection over which element repeat operates. The initial instance data supplies the prototypical member of the homogeneous collection, and this is used during UI initialization—4.2.4 The xforms-ui-initialize Event—to construct the members of the homogeneous collection. This prototypical instance is also used by action insert when creating new members of the collection. To create homogeneous collections, the initial instance data must specify at least one member of the collection; this requirement is similar to requiring instance data in addition to a schema, and the same justification applies.

The form controls appearing inside repeat need to be suitable for populating individual items of the collection. A simple but powerful consequence of the above is that if the XForms Model specifies nested collections, then a corresponding user interface can nest repeat elements.

9.3.9 Nested Repeats

It is possible to nest repeat elements to create more powerful user interface for editing structured data. G.2 Editing Hierarchical Bookmarks Using XForms is an example of a form using nested repeats to edit hierarchical data consisting of bookmarks within multiple sections. Notice that an inner repeat's index always starts from 1. Consider the following insert statement that appears as part of that example.

Example: Repeat Index and Nested Repeats
<xforms:insert
  nodeset="/bookmarks/section[index('repeatSections')]/bookmark"
  at="index('repeatBookmarks')"
  position="after"/>

The above insert statement is used in that example to add new bookmark entries into the currently selected section. The inner (nested) repeat operates on bookmarks in this selected section; The index—as returned by XForms function index—for this inner repeat starts at 1. Hence, after a new empty section of bookmarks is created and becomes current, the first insert bookmark operation adds the newly created bookmark at the front of the list.

9.3.10 User Interface Interaction

Element repeat enables the binding of user interaction to a homogeneous collection. The number of displayed items might be less than the total number available in the collection. In this case, the presentation would render only a portion of the repeating items at a given time. For example, a graphical user interface might present a scrolling table. The current item indicated by the repeat index should be presented at all times, for example, not allowed to scroll out of view. The XForms Actions enumerated at 10 XForms Actions may be used within event listeners to manipulate the homogeneous collection being populated by scrolling, inserting, and deleting entries.

Notice that the markup encapsulated by element repeat acts as the template for the user interaction that is presented to the user. As a consequence, it is not possible to refer to portions of the generated user interface via statically authored idref attributes. A necessary consequence of this is that XForms 1.0 does not specify the behavior of construct switch within element repeat. Future versions of XForms may specify the behavior of switch inside repeat based on implementation experience and user feedback.