I know, I know … when you talk about a series, it usually implies that the articles will be somewhat closer together than the ones for my Understanding XForms series has been. Mea culpa. The last couple of months have been busy, but a desire to wrap up my Firefox book (another mea culpa, if it comes to that) has combined with being fairly deeply immersed in the vagaries of XForms on Firefox to prompt me to write the third installment in this series. Take a look at the links at the end of the article for the previous installments.
Please note in all of these that the assumption being made that the examples given here, if run in Mozilla Firefox, need the Xforms extension available at http://www.mozilla.org/projects/xforms/download.html. However, the examples should (in general) run in most contemporary XForms enabled browsers (a topic I’ll be discussing a couple of columns from now).
The Joy of XForms Components
Big complex data models look really imposing and impressive, but at the end of the day,
XForms got their start largely because the existing HTML forms just weren’t expressive
enough. Consider some of the more vexing problems associated with typical web forms.
Suppose that you wished to:
choose a value from a given numeric range, rather than from a drop-down list?
create an invoice where you needed to add items to an invoice list?
enter a date in a consistent numerical format?
allow data into a text field that corresponded to a given regular expression
pattern?
create tabbed panes of content?
create a wizard for gathering information?
All of these things can, of course, be done with the careful application of JavaScript,
server side code, and perhaps third party plugins. The problem though is that most of
these things are also fairly common operations in more traditional stand-alone
applications, which has often spelled real trouble when such applications were then
ported from the web. Moreover, there are no consistent standards from such solutions
that seem to work universally on the web, especially from the standpoint of being able
to tie such components into the bigger framework of web pages and CSS.
Thus, as the XForms working group within the W3C tried to grapple with making web
components more application like, they also began to see the need to define more
sophisticated structures for handling the use cases that arose in any number of business
applications.
Consequently, one of the first things that came out of the working group was the
realization that a component standard should be more concerned with interface
requirements than it should be with presentation. In other words, XForms components
needed to be abstract.
This notion is of course hardly foreign to HTML, but it is one that tends to be foreign
to a lot of people who work regularly with web forms. The first pass of Web forms
defined the notion of the field, with an associated type
attribute that would determine whether it was an text box, a check box, a radio button,
in short, everything that didn’t involve selecting from a list or dealing with multiline
content.
There are several things wrong with this approach, things that only became obvious in
retrospect. First of all, there are significant qualitative differences between a box of
text and a checkbox - one can take potentially any string, the other can only hold one
of four well defined state values (selected, unselected, disabled and indeterminate).
This meant that the same statement needed to essentially be
treated as perhaps half a dozen distinct elements, each with its own attributes, events
properties and methods. This in turn made validation considerably more difficult, and
became really hairy in the case of such things as radio buttons, which generally have no
semantic meaning outside of groups).
Moreover, such components are fundamentally dumb. You can use script to handle
manipulation of content, but its remarkable just how ugly such computations can be for
even the simplest of operations. For instance,consider the following form fragment:
+
Not only do you have the fairly complex bit of manipulation when the “=” button is
pressed just to add two numbers, but you are outputting to an input box, which means
that a user could go in and change this field. Moreover, the “=” button has a largely
spurious value - if this form was submitted this information would go with it even
though it makes no different to the model.
Now compare this to the XForm way of doing things:
+ =
In this particular case, you are trading the complexity of DOM manipulation in Javascript
for the complexity of creating a data model. Once that model is defined, however, you
suddenly have components that are aware of one another through the data model - if you
change the value in either field a or field b, not only does it change the data model,
but that change then gets propagated back to a new element - the
The element is one of those which, once you start using it, you
begin to wonder why it never ended up in the initial HTML set. It is a non-editable
component that can either reflect the value of a given item in the data-model (via the
ref attribute), or can reflect the result of a calculation (using XPath
notation) via the value attribute.
Both the and
+ =
The output object (generally) only displays text content, though I’ll show some examples
in the next column (customizing XForms) to demonstrate how to display other things,
making the component considerably more useful.
One thing that you may notice if you are following along in this demonstration - when you type an entry into one of the input fields, nothing happens until you change the focus (by tabbing out or clicking outside of the control). This feature is built into XForms in order to insure that the proper processing can be handled in lower-capability devices. You can, however, change this behavior by including the attribute incremental=”true” on the input control in question. Once this happens, the component will force an update automatically whenever a change occurs. This becomes even more important when dealing with styling and customization issues.
One of the more frustrating elements missing from the set of core HTML tools is a simple
slider, that lets you select between a range of numeric values. The
component does precisely that. By specifying the start,
end and an optional step value, you can create a slider that will let
you select either a discrete or continuous value from that range (depending upon step).
For instance, the following XHTML document uses two sliders to create a coordinate value
(x,y) where both x and y can be expressed in 0.05 step intervals:
|
|
Most controls, including the control, also have the ability to
specify a few subtags, such as the
Coordinate: This is a coordinate somewhere within the unit square.
Note that unlike with straight XHTML, white space is preserved, so you should be
very careful about this when designing your own xforms pages. This final form can be
seen in Figure 1:
Figure 1. XForm range controls
There are also two “specialty” input forms - the form, which is
used for specifying password information in a way that you don’t want someone looking
over your shoulder to see (and is the direct analog of the
type=”password”> HTML element), and the component, which
lets you select a file from your current file system (either local or extended). The
upload control tends to be fairly complex, as is illustrated below:
The tag places the URI in question into the appropriate
referenced item, with the selected media-type ending up in the mediatype element and
size giving the size in bytes. At least in the Firefox implementation, I couldn’t get it
to differentiate between different media types (it would always assume “*.*” as a file
pattern), but otherwise brought up the appropriate file open dialog and populated the
resulting field accordingly. (I have more to talk about on the submission side, but that
will have to wait for THAT particular column as well … oh, man, am I committing myself
here!)
The one holdout to all of this text entry is the
Dealing with Selections
Few areas of forms are as frought with problems as the need to select one item (or more)
from many. In HTML, most of the selection capability is scattered among four different
types of controls - drop-down selection boxes, radio buttons, checkboxes and
You can see all of these as a screenshot in Figure 2.
Figure 2. Select and Select1 controls
Grouping and Repeating
One of the more significant things that XForms introduces into a
web page is the notion of context. If you’re familiar with XPath or XSLT,
context should be clear, but for those that are coming to XForms from
a different direction, context can be thought of as the place within an
XML document where all XPath operations are based.
You can see the context at work in the element:
the nodeset identifies the elements that will provide the data (in this case all XML nodes retrieved at
instance(’lang_colors’)/d:colorset[@lang = instance(’dataStore’)/@lang]/d:color, while the label and value assume each of these nodes as a current content and provide the XPath only relative to those elements.
The element serves a number of functions, but perhaps its most important is to change the context of everything within it. Taking a ref attribute, the group serves to anchor a given context so that anything within it is given relative to the group. For instance, suppose that you start with a model giving a person’s name and address, you could either give this information using absolute XPath expressions (which include a lot of redundancy) or you could use the power of groups to better organize the content:
kcagleKurtACagleMale1962-02-211313 Mockingbird LaneVictoriaBritish ColumbiaCanadaadelamareAleriaBDelamareFemale1981-11-06123 Sesame StreetNew YorkNew YorkUnited States
Without Grouping
User Information
First Name: Middle Initial: Surname:
Address
Street: City: Region: Country:
With Grouping
User Information
First Name: Middle Initial: Surname:
Address
Street: City: Region: Country:
What’s more, by working with such groups, you are better able to leverage XPath for controlling content display while at the same time keeping internal structure the same. For instance, you could actually have a controller that will show different records using a select1 control (illustrated in Figure 3):
kcagleKurtACagleMale1962-02-211313 Mockingbird LaneVictoriaBritish ColumbiaCanadaadelamareAleriaBDelamareFemale1981-11-06123 Sesame StreetNew YorkNew YorkUnited States
User Information for
First Name: Middle Initial: Surname:
Address
Street: City: Region: Country:
Figure 3. Use of the group control.
In this particular case powerfully illustrates the concept of grouping - the local information contained within the displayed record remains the same, but by switching contexts via the select1 object, you have the ability to migrate through multiple records effortlessly. Now, in this case the assumption is made that ALL of these records are locally available, making this at best an impractical situation for large databases, but the goal here is more to illustrate how groups can be used to create context switches.
The notion of context also plays a significant role in another XForms-only feature, the ability to repeat through all items that share a given context specification. For instance, in the previous example, the specific nodeset “d:record” points not to one record but to all records in the collection. By using the element, it is possible to iterate through all of the records and display them. For instance, the following will repeat the input fields for all of the record nodes from the previous example, as shown in Figure 4.
kcagleKurtACagleMale1962-02-211313 Mockingbird LaneVictoriaBritish ColumbiaCanadaadelamareAleriaBDelamareFemale1981-11-06123 Sesame StreetNew YorkNew YorkUnited StatestdimeonTheodoreADimeonMale1972-05-1131416 Pi St.OlympiaWashingtonUnited States
Figure 4. Use of the repeat control.
If there is only one node, then the repeat tag acts much like a group tag. In the current
Firefox implementation of XForms, there are some odd interactions between group and repeat elements that occasionally can make for some unpredictable behavior. In this case, you can substitute repeat for group without much difference, save that a element takes a nodeset attribute, while a element takes a ref attribute.
Summary
While this does not represent the whole spectrum of components, it covers those that can operate without needing to understanding the eventing model currently used by XForms, so this seems a good point to break. In the next column on XForms I will cover the use of CSS and XBL Bindings to change the behavior of XForms, and in the final column will look at the XForms event model and how it makes possible such things as wizards and multipage forms.
Kurt Cagle is an author and computer consultant specializing in AJAX and Web 2.0 technologies. He lives in Victoria, British Columbia, and is slowly learning how to say ‘eh’.