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

9.1 group

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

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

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

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.

9.2 switch

The XForms model allows the authoring of dynamic user interfaces that vary based on the current state of the instance data being populated—see model item property relevant 6.1.4 relevant. 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 example is when the underlying XForms model contains conditional structures.

This section defines construct switch that allows the creation of user interfaces where the user interface can be varied based on user actions and events. Element switch contains one or more case elements. Markup contained within element case specifies the user interface that is displayed when that case is selected. Boolean attribute selected of element case determines the selected state and can be manipulated programmatically via the DOM, or declaratively via XForms action toggle. Attribute id of case is used within action toggle for this purpose. The following example demonstrates the use of switch.

switch
<switch id="sw">
  <case id="in" selected="true">
    <input ref="yourname">
      <caption>Please tell me your name</caption>
      <action ev:event="activate">
        <toggle case="out"/>
      </action>
    </input>
  </case>
  <case id="out" selected="false">
    <html:p>Hello <output ref="yourname" />.
      <button id="editButton">
        <caption>Edit</caption>
        <action id="editAction" ev:event="activate">
          <toggle case="in"/>
        </action>
      </button>
    </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 return results in XForms event activate. Event activate is handled by the attached handler—element action. This handler uses XForms action toggle to select the case with id="out". This sets attribute selected on case id="out" to true. The markup contained in the selected case displays the name the user entered along with an edit button. Activating the edit button in turn results in the attached handler selecting case id="in".

XML Representation: <switch>
<switch
  (common attributes)
>
  <!-- case+ -->
</switch>

(common attributes) - defined in 8.12.1 Common Attributes

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.

9.3 repeat

The XForms Model 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. 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.

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

Element repeat operates over a homogeneous collection by binding the encapsulated user interface controls to each element of the collection. Attributes on element repeat specify how many members of the collection are presented to the user at any given time. XForms actions insert, delete and setRepeatCursor 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 (assuming four item elements in the returned node-set):

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

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">
    <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="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="activate" nodeset="my:lines/my:line"
          at="cursor('lineset')"/>
</button>
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 in 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.

9.3.1 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 xforms:UIInitialize), 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 cursor 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 user interface markup for repeating structures adds encapsulation metadata about the collection being populated. The processing model for repeating structures uses a cursor that points to the current item in the data instance. This repeat cursor is accessed via XForms extension functions cursor 7.4.2.5 cursor() and manipulated via XForms action setRepeatCursor 10.10 setRepeatCursor. This cursor 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 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—this ensures that the node-set represent a homogeneous collection. The behavior of element repeat with respect to other XPath node-sets is undefined. The initial instance data supplies the prototypical member of the homogeneous collection, and this is used during UI initialization—4.2.4 xforms:UIInitialize—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.2 Nested Repeats

It is possible to nest repeat elements to create more powerful user interface for editing structured data. E.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 cursor always starts from 1. Consider the following insert statement that appears as part of that example.

Repeat Cursor And Nested Repeats
<xforms:insert
  nodeset="/bookmarks/section[cursor('repeatSections')]/bookmark"
  at="cursor('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 cursor—as returned by XForms function cursor—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.3 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 cursor 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.