10 XForms User Interface

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

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.

10.1 Grouping Form Controls

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

Example: XML Representation: <group>
<group
  (single node binding attributes)
  (common attributes)
>
  <!-- caption?, ##all -->
</group>

(single node binding attributes) - Selection of instance data node, defined at 8.12.2 Single Node Binding Attributes
(common attributes) - defined in 8.12.1 Common Attributes

Example: Grouping Related Controls
<group ref="address">
  <caption>Shipping Address</caption>
  <input ref="line_1" >
    <caption>Address line 1</caption>
  </input>
  <input ref="line_2" >
    <caption>Address line 2</caption>
  </input>
  <input ref="postcode">
    <caption>Postcode</caption>
  </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 tabbing order within that group.

10.2 Conditional Constructs For Dynamic User Interfaces

The XForms User Interface allows the authoring of dynamic user interfaces, i.e., user interfaces that vary based on the current state of the instance data being populated. 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?'. Another use case for such dynamic user interfaces is when the underlying XForms Model contains conditional structures.

This element contains one or more case elements. Each case has an id attribute that is used within event handlers to activate or deactivate that portion of the user interface created by the markup contained within that case element.The attribute selected provides an initial selected case, as well as provides access to the currently selected case, through live updates to the attribute values in the containing document. This example shows how to provide a conditional user interface.

Example: switch
<switch id="sw">
  <case id="in" selected="true">
    <input ref="yourname">
      <caption>Please tell me your name</caption>
    </input>
  </case>
  <case id="out" selected="false">
    <html:p>Hello <output ref="yourname" />.</html:p>
  </case>
</switch>

The above results in the portion of the user interface contained in the first the case being initially displayed. The XForms Action toggle activates and deactivates different portions of this conditional construct.

Example: XML Representation: <switch>
<switch
  (single node binding attributes)
  (common attributes)
>
  <!-- case+ -->
</switch>

(single node binding attributes) - Selection of instance data node, defined at 8.12.2 Single Node Binding Attributes
(common attributes) - defined in 8.12.1 Common Attributes
- optional selector for initial case.

Example: XML Representation: <case>
<case
  selected = xsd:boolean
>
  <!-- ##any -->
</case>

selected = xsd:boolean - optional selection status for the case.

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.

10.3 Repeating Structures

The XForms Model allows the definition of repeating structures such as multiple items being purchased within a purchase order. When defining the XForms Model, such higher-level aggregations are constructed out of basic building blocks; similarly, this section defines higher-level user interface constructs that build on the form controls defined previously that can bind to data structures such as lists and collections. Element repeat encapsulates a UI mapping over a homogeneous collection, in other words, a collection consisting of data items having the same type and structure.

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

Note that controls for adding or removing repeating entries may appear within the repeat, (causing the add/remove controls themselves to repeat), or may appear outside the repeat.

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 (assuming four item elements in the returned node-set):

<!-- 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 model item for the collection being populated would typically have defined attributes 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. Event listeners separately control UI aspects such as scrolling and insertion. This specification does not specify normative means for displaying such add and delete controls; as with the rest of the XForms User Interface design, these are left to be flexible while showing a default presentation.

<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">
    <caption>Line Item</caption>
  </input>
  <input ref="@name">
    <caption>Name</caption>
  </input>
</repeat>

<button>
  <caption>Insert a new item after the current one</caption>
  <action ev:event="ev:activate">
    <insert nodeset="my:lines/my:line"
            at="cursor('lineset')"
            position="after"/>
    <setValue ref="my:lines/my:line[cursor('lineset')]/@name"/>
    <setValue ref="my:lines/my:line[cursor('lineset')]/price">0.00</setValue>
  </action>  
</button>

<button>
  <caption>remove current item</caption>
  <delete ev:event="ev:activate" nodeset="my:lines/my:line"
          at="cursor('lineset')"/>
</button>
Example: XML Representation: <repeat>
<repeat
  (node-set binding attributes)
  (common attributes)
  startIndex = xsd:positiveInteger : 1
  number = xsd:nonNegativeInteger
>
  <!-- ##any -->
</repeat>

(nodeset binding attributes) - Selection of context node-set, defined at 8.12.3 Nodeset Binding Attributes
(common attributes) - defined in 8.12.1 Common Attributes
startIndex - 1-based hint to the XForms Processor as to which starting element from the collection to display.
number - hint to the XForms Processor as to how many elements from the collection to display.

10.3.1 Repeat Processing

The user interface markup for repeating structures adds encapsulation metadata about the collection being populated. Processing for repeating structures takes into account a cursor that points to a current item in the data instance. This cursor is used as a reference point for insert and delete XForms Actions.

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 repeatCursor.

Repeat processing uses XPath expressions to address the collection over which element repeat operates. The XPath expression used as the value of attribute nodeset must select a node-set 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 other XPath node-sets is undefined.

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. The form controls appearing inside repeat need to be suitable for populating individual items of the collection.

The XForms Actions enumerated at 9 XForms Actions may be used within event listeners attached to button elements placed inside the body of construct repeat.

10.3.2 User Interface Interaction

As specified, element repeat allows us to bind a user interface to a dynamic homogeneous collection.

The number of displayed items might be less than the total number available. In such a case, the presentation would only render 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 cursor should be presented at all times, for example, not allowed to scroll out of view.