Table of Contents | Prev | Next | Bottom |
Quick Table of Contents |
---|
9 XForms User Interface 9.1 Grouping Form Controls 9.2 Conditional Constructs For Dynamic User Interfaces 9.3 Repeating Structures 9.3.1 Repeat Processing 9.3.2 User Interface Interaction 9.4 Dynamic Selection Choices 9.5 Reusable Form Controls |
This chapter covers XForms features for combining form controls into user interfaces.
All form controls defined in 7 Form Controls are treated as individual inline 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 examle, if the user interface needs to be split up amongst several screens, controls appearing inside the same aggregation would typically be rendered on the same screen or page.
The group
element is used as a container for defining a
hierarchy of form controls. Groups can be nested to create complex
hierarchies.
group
>
<group (single node binding attributes) (common attributes) > <!-- ((any form control) | group | repeat | component | switch )* --> </group>
(single node binding attributes) - Selection of instance data node, defined at 7.14.2 Single Node Binding Attributes
(common attributes) - defined in 7.14.1 Common Attributes
In CSS-based layout systems, groups lay out their children using a
constraint-based system that supports both relative flexible sizing and
intrinsic sizing. Through CSS, an inline box can be specified using the display
property with a value of inline
. A block-level group can be specified with a value of block
, which is the default.
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 lowest
form control in the tabbing order within that group.
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 appearing within form
controls to activate or deactivate that portion of the user interface created
by the markup contained within that case
element.
This example shows how to provide a conditional user interface--either input or output:
<switch id="sw"> <case id="in"> <input ref="yourname"> <caption>Please tell me your name</caption> </input> </case> <case id="out"> <html:p>Hello <output ref="yourname" />.</html:p> </case> </switch>
The above will result in the portion of the user interface contained
within the default case being initially displayed. The XForms Action toggle
activates and deactivates
different portions of this conditional construct.
switch
>
<switch (single node binding attributes) (common attributes) default = xsd:IDREF > <!-- case+ --> </switch>
(single node binding attributes) - Selection of instance data node, defined at 7.14.2 Single Node Binding Attributes
(common attributes) - defined in 7.14.1 Common Attributes
default = xsd:IDREF - optional selector for initial case.
case
>
<case id = xsd:ID > <!-- ##any --> </case>
id = xsd:ID - required unique identifier.
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, here are defined 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
represents a UI mappings over homogenous
collection, in other words, a collection consisting entirely of like form
controls.
<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 the repeat processing (modulo 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 will 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.
repeat
>
<repeat (nodeset binding attributes) (common attributes) startIndex = xsd:positiveInteger : 1 number = xsd:nonNegativeInteger > <!-- ##any --> </repeat>
(nodeset binding attributes) - Selection of context node-set, defined at 7.14.3 Nodeset Binding Attributes
(common attributes) - defined in 7.14.1 Common Attributes
startIndex = xsd:positiveInteger : 1 - 1-based hint to the XForms Processor as to which starting element from the collection to display.
number = xsd:nonNegativeInteger - hint to the XForms Processor as to how many elements from the collection to display.
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. This cursor is used as a reference point for insert
and delete
XForms Actions. These, along with setRepeatCursor
, can be thought of as the markup equivalent of limited DOM access to
the markup constructed by repeat
.
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. But as a consequence, the user interface cannot bind
to an element from the underlying collection out of sequence
except by using an absolute XPath expression.
The binding expression attached to the repeating sequence
returns a node-set of the collection being populated, not an indiviual node.
Within the body of element repeat
binding expressions are evaluated
with a context node of the node determined by the repeatCursor.
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 8 XForms Actions may be used
within event listeners attached to button
elements placed inside the
body of construct repeat
. In combination with the facilities provided
by element group
and CSS layout, this allows document authors to
customize the positioning of controls for standard actions such as insert or
delete.
As specified, element repeat
allows us to bind a
user interface to a dynamic homogenous 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 attributes startIndex
and
number
provide hints to the user interface as to which elements
should be displayed initially.
The XForms Actions setRepeatCursor
and scroll
adjust the internal startIndex
as needed to ensure that currently active items in the repeating
sequence are presented to the user.
XForms defines list controls selectOne
and selectMany
. By
default, these follow the standard form control behavior of representing their
state as a Schema simpleType that is associated with an instance data
node--often a derived-by-list datatype. Often, a more convenient representation
for lists is using markup instead of whitespace to separate list items. This
section explains additional XForms processing to handle this common case.
Notice that this usage matches the case of selection controls
selectOne
and selectMany
where the user is allowed to select
from a set of dynamic choices, i.e., where the list of choices is determined at
run-time as opposed to authoring time. As a consequence, this working draft
proposes the construct repeat
as the means to represent dynamic
choices for controls selectOne
and selectMany
.
In this case, binding attribute nodeset
on element
repeat
specifies the location in the instance that contains the
dynamically determined set of choices. The contained form controls within
element repeat
specify the user interface for one element from the
dynamic list as before. Semantics of the repeat cursor are as
defined earlier.
<selectOne ref="/trip/reservation/flight"> <caption>Available Flights</caption> <help>Displaying list of available flights matching your requirements, please pick one.</help> <!-- /trip/available/flights is populated by a sequence of --> <!-- <flight> elements at run time--> <repeat nodeset="/trip/availableFlights/flight"> <!--itemrefs that point to <flight> nodes --> </repeat> </selectOne>
In the above, the user is able to select a flight from a dynamically
created list of available flights. The user interface template encapsulated
within the body of element repeat
is used in creating a choice
item for each flight
element found in
/trip/availableFlights
.
User Interface templates allow the creation of reusable user interface components. Just as authors can define data types and structures that can be reused within the XForms Model, reusable user interface components allow us to design complex user interfaces using the basic building blocks described in the previous section, and then reuse these components in multiple situations. As with any component framework, this has two basic requirements:
Components need to declare what aspects of the component are parameterizable by the caller.
The caller needs to be able to override the default values of the parameters declared in the component.
This section describes such a component framework along with sample markup.
This component mechanism has some similarities with the user interface used
within the body of element repeat
to provide the user interface for a
generic element of the nodeset operated on by element repeat
. Those
templates can be thought of as anonymous components.
This consists of:
XForms user interface construct defComponent
defined next
corresponds to creating re-usable data types.
Using XForms user interface construct component
to instantiate
reusable components declared using defComponent
corresponds to
creating data instances corresponding to a reusable user defined
data type.
this example, assume that USShippingAddress
is a reusable data type that is used in multiple places in the
XForms Model, e.g. the user will be
asked for a billingAddress
and shippingAddress
--both of type USShippingAddress
.
The following shows a simple example that is designed to bind an XForms
form control to a model item of type address
with no attention to making the component reusable.
<group ref="address"> <input ref="street"> <caption>Please enter your street address</caption> </input> <input ref="zip"> <caption>Zip Code</caption> </input> </group>
Next, consider the above fragment modified to become a reusable component that could be used for obtaining both the shipping and billing address. To do this, those portions of the component that the caller will wish to modify need to be parameterized.
<defComponent id="AddressWidget"> <param name="streetPrompt"/> <param name="zipPrompt"/> <group ref="address"> <input ref="street"> <caption><valueOf select="$streetPrompt"/></caption> </input> <input ref="zip"> <caption><valueOf select="$zipPrompt"/></caption> </input> </group> </defComponent>
Note that the markup shown above does not create a user interface; user
interface is created by explicitly instantiating the component via element component
described next.
With this, the component can be instantiate in the user interface for obtaining the shipping and billing address:
<component ref="myAddress" component="AddressWidget"> <param name="streetPrompt" value="Shipping Street Address"/> <param name="zipPrompt" value="Zip Code for shipping state"/> </component>
The reusable component is instantiated by element component
;
parameter values are specified by the contained param
elements.
<defComponent id = xsd:ID > <!-- param*, ((any form control) | group | repeat | component | switch )* --> </defComponent>
id = xsd:ID - required unique identifier.
<param id = xsd:ID name = xsd:NMTOKEN value = xsd:string > <!-- ##empty --> </param>
id = xsd:ID - optional unique identifier.
name = xsd:NMTOKEN - required parameter name
value = xsd:string - optional parameter value
<valueOf id = xsd:ID select = xsd:string > <!-- ##empty --> </valueOf>
id = xsd:ID - required unique identifier.
select = xsd:string - reference to a parameter
<component (single node binding attributes) (common attributes) component = xsd:IDREF > <!-- param* --> </component>
(single node binding attributes) - Selection of instance data node, defined at 7.14.2 Single Node Binding Attributes
(common attributes) - defined in 7.14.1 Common Attributes
component = xsd:IDREF - reference to thedefComponent
.
Table of Contents | Top |