You are reading O'Reilly XForms Essentials by Micah Dubinko. (What is this?) - Buy XForms Essentials Online

Form Design Patterns

A design pattern is a recurring set of solutions to common problems, written down in such a way as to help designers apply them to new problems—avoiding the pain of having to rediscover them. The popular 1995 book Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley)[6] helped make many developers aware of design patterns. Since then, many other fields, mostly computer-related, have agreed upon design patterns. The following sections describe design patterns for XForms, including the four pieces of information that Design Patterns made popular. Each pattern includes:

  1. A problem definition

  2. A solution description

  3. A discussion of consequences and trade-offs

Each section also contains sample code to illustrate the pattern.

Problem: XPath expressions used by XForms can get extremely complicated, and keeping track of context nodes and other details can obscure the details of what's happening in a form.

Solution: It is possible to author a form in such a way that the only XPath expressions used are simple names, much like the departing HTML forms technology. To do this, the structure of the user interface elements must match the structure of the instance data. Additional levels of UI nesting can be accomplished with group elements, so that instance data like this:

<purchaseOrder>
  <items>
    <item partNum="1234">
      <quantity/>
    </item>
  </items>
</purchaseOrder>

would have a matching user interface like this:

<group name="items">
  <group name="item">
    <input ref="@partNum">...</input>
    <input ref="quantity">...</input>
  </group>
</group>

Note that the root element purchaseOrder, already a default context node, doesn't need a supporting group element.

Consequences: This design pattern is mutually exclusive with the Design by Buddy System pattern, which doesn't use XPath binding expressions on form controls. The resulting XPath expressions contain no complicated syntax, and (other than the leading @ symbol for attributes) could pass for the simple names used in HTML forms. One disadvantage is that extra syntax is needed, to provide nested group elements that each provide a single step in the XML path. A hybrid approach could use a single outer group element, with a full XPath expression, like this:

<group name="items/item">
  <input ref="@partNum">...</input>
  <input ref="quantity">...</input>
</group>

Problem: Designing a form takes both technical skills, to get the data portions operating correctly, and graphical design skills, to make the layout attractive and easy to use. Often, a single person doesn't have all the necessary skills.

Solution: XForms makes it possible to divide form authoring cleanly between two individuals or teams. One person can design the XML and data side, and the other can lay out the form controls. The key to dividing the labor is in the interface between form controls, which can use the bind attribute to provide a consistent and XPath-free interface. Using this system, the designers would first come up with a list of the needed form controls, assigning each one a short name, something like that shown in Table 10.1, “Form design by buddy system ”.

From this agreement, the data designer could begin authoring the XForms Model, including the structure of the XML to be submitted, and any validations or calculations needed. As part of authoring, a number of bind elements will need to be created. For each, the data designer assigns the id from the Name column above. The result, using a mythical xml:id attribute, would look something like this:

<xforms:model>
  <xforms:instance>
    <session>
      <name>
        <given/>
        <family/>
      </name>
      <pref/>
      <password/>
    </session>
  <xforms:instance>
  <xforms:submission ... />
  <xforms:bind nodeset="name/given" xml:id="fname" ... />
  <xforms:bind nodeset="name/family" xml:id="lname" ... />
  <xforms:bind nodeset="pref" xml:id="webpref" ... />
  <xforms:bind nodeset="password" xml:id="pass" ... />
</xforms:model>

At the same time, the graphical designer can begin incorporating XForms form controls into the layout of the web or printed page. For each form control, the graphic designer applies a bind attribute with a name agreed upon earlier, producing something like this:

...
  <xforms:input bind="fname" ... />
...
  <xforms:input bind="lname" ... />
...
  <xforms:select1 bind="webpref" ... />
...
  <xforms:password bind="pass" ... />
...

The result is a fully-functional form; to those filling out the form, there would be no apparent differences between this and a single-source authored form.

Consequences: This design pattern is mutually exclusive with the Stepwise XPath pattern. Overall, designing a form in this manner is slightly more work overall, though that is offset by dividing the work into two parts.

Problem: Different users often prefer different languages, and in current form systems it is very difficult to deliver a form that is in the desired language. Conventional form engines usually have to dynamically assemble a form every time it's delivered, so it's not much additional effort to dynamically place all the text on the form. In XForms, however, it's more common to have a static form, with dynamic XML data.

Solution: Pervasive throughout XForms is the idea that any content presented to the user should be able to have roots in XML instance data. This is true for form controls, labels, help/hint/alert messages, and XForms Actions such as message and load. Even ancillary text can be taken from XML and displayed using the output form control. For example, a form like this:

<p>Please complete the following questions:</p>
<input bind="term">
  <label>Search:</label>
</input>
<select bind="where">
  <label>Search the following areas of the web site:</label>
  <item>
    <label>Product Information</label>
    <value>p</value>
  </item>
  <item>
    <label>Technical Support</label>
    <value>t</value>
  </item>
  <item>
    <label>Developer Resources</label>
    <value>d</value>
  </item>
</select>

might be changed so that all displayed strings come from a secondary instance document:

<p><output ref="instance('strings')/msg.top"/></p>
<input bind="term">
  <label ref="instance('strings')/label.term"/>
</input>
<select bind="where">
  <label ref="instance('strings')/label.where"/>
  <item>
    <label ref="instance('strings')/label.where.item1"/>
    <value>p</value>
  </item>
  <item>
    <label ref="instance('strings')/label.where.item2"/>
    <value>t</value>
  </item>
  <item>
     <label ref="instance('strings')/label.where.item3"/>
    <value>d</value>
  </item>
</select>

Note that no strings intended for presentation to the user remain. Each place where a string used to be is replaced by a reference to an instance named strings, with an informal naming convention. The addition of one line to the XForms Model:

<instance id="strings" src="path-to-xml-file.xml"/>

points to an external XML file containing the strings. The file would look something like this:

<strings>
  <msg.top>Please complete the following questions:</msg.top>
  <label.term>Search:</label.term>
  <label.where>Search the following areas of the web site:</label.where>
  <label.where.item1>Product Information</label.where.item1>
  <label.where.item2>Technical Support</label.where.item2>
  <label.where.item3>Developer Resources</label.where.item3>
</strings>

With all the strings in a single place, it could easily be translated into something else, say, Spanish.

<strings>
  <msg.top>Favor de terminar las preguntas siguientes:</msg.top>
  <label.term>Buscar:</label.term>
  <label.where>Busque las áreas siquientes del Web site:</label.where>
  <label.where.item1>Información de Producto</label.where.item1>
  <label.where.item2>Ayuda Técnica</label.where.item2>
  <label.where.item3>Recursos para Desarrolladores</label.where.item3>
</strings

Modern web servers have the capability to perform content negotiation, delivering a file in a language requested by a particular browser. Using this capability, a single static form can be delivered in multiple languages. For example, instructions for Apache can be found at http://www.apacheweek.com/features/negotiation.

Consequences: Overall, this technique involves significantly more setup than just hard-coding a single language. Setting up a web server to deliver different versions of a file based on language preferences can still be difficult, though the situation is improving. On the other hand, compared to the effort of re-creating the same form over and over again in different languages, this technique is more efficient when many languages need to be supported.



[6] By the so-called "gang of four": Gamma, Helm, Johnson, and Vlissides.