W3C

XForms for HTML Authors

Steven Pemberton, W3C/CWI

Version date: 2006-07-21

Introduction

XForms is the new markup language for forms on the Web. This document is a quick introduction to XForms for HTML Forms authors. It shows you how to convert existing forms to their XForms equivalent. It assumes knowledge of HTML Forms, so is not a beginner's tutorial. Although there is mention of additional facilities of XForms beyond those possible in HTML Forms (marked with an asterisk on the headings), it is not a full tutorial on all features of XForms. Part 2 deals with additional features that are not available in HTML Forms.

Table of Contents

  1. A Simple Search Form
    Namespace Prefixes
  2. Forms Controls
    Simple Text Input
    Textarea
    Radio Buttons
    Checkboxes
    Menus
    File Select
    Passwords
    Buttons
    Image Buttons
    Reset
    Optgroup
    Grouping Controls
    Output Controls*
    Range Controls*
    Hidden Controls
  3. Submitted Values
    Making the Submitted Values Explicit
    Initial Values
    Hidden Values
    Getting Initial Values From Elsewhere*
    'Editing' any XML document*
  4. Submitting
    Multiple Submissions*
    Submission Methods
    Life after Submit*
  5. Controlling Controls
    Disabled Controls
    Readonly Controls
    Required Controls*
    Constraint Property*
    Calculate Property*
    Types*
    Combining Properties*
  6. More than One Form in a Document
    Bind instead of Ref
  7. Features Not Handled Here

*Features not present in HTML Forms

A Simple Search Form

Take this simple HTML form:

<html>
<head><title>Search</title></head>
<body>
    <form action="http://example.com/search"
          method="get">
         Find <input type="text" name="q">
         <input type="submit" value="Go">
    </form>
</body>
</html>

The main difference in XForms is that details of the values collected and how to submit them are gathered in the head, in an element called model; only the form controls are put in the body. So in this case the minimum you need to put in the head is:

<model>
   <submission action="http://example.com/search"
               method="get"
               id="s"/>
</model>

(Elements and attributes in XForms are in lower case.)

The <form> element is now no longer needed; the controls in the body look like this:

<input ref="q"><label>Find</label></input>
<submit submission="s"><label>Go</label></submit>

What you can hopefully work out from this is that form controls have a <label> element as child, the <input> uses "ref" instead of "name", and there is a separate submit control that links to the details of the submission in the head. So the complete example is:

<h:html xmlns:h="http://www.w3.org/1999/xhtml"
       xmlns="http://www.w3.org/2002/xforms">
<h:head>
    <h:title>Search</h:title>
    <model>
        <submission action="http://example.com/search"
                    method="get" id="s"/>
    </model>
</h:head>
<h:body>
    <h:p>
        <input ref="q"><label>Find</label></input>        <submit submission="s"><label>Go</label></submit>
    </h:p>
</h:body>
</h:html>

Namespace Prefixes

Another obvious difference is the use of h: prefixes on the HTML elements. This has nothing to do with XForms, but with XML which is designed to allow you to combine different languages together. XForms is designed to be combined with different languages, not just XHTML. XML processors need to be told which language different elements belong to, though one language may be the 'default' language. In the above document, XForms has been made the default, though XHTML could have been made the default by changing the xmlns attributes in the head:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://www.w3.org/2002/xforms">
<head>
    <title>Search</title>
    <f:model>
        <f:submission action="http://example.com/search"
                      method="get" id="s"/>
    </f:model>
</head>
<body>
    <p>
        <f:input ref="q"><f:label>Find</f:label></f:input>
        <f:submit submission="s"><f:label>Go</f:label></f:submit>
    </p>
</body>
</html>

The choice is yours. You can also choose to make neither the default, and prefix all elements. You can choose any prefix; h: or x: or html: or form:, it's up to you.

In the future, XHTML2 will allow you to write forms without prefixes.

Forms Controls

XForms provides equivalents of all HTML Form controls. But there is a major difference in approach: HTML mainly specifies how the control should look, while XForms specifies what the control should do. So while the HTML specification says that the select element creates a menu, and the radio type of input creates radio buttons that allow a single choice to be made, XForms has the select and select1 elements, which only specify the intent of the controls, to select zero or more, or only one, element from a list. How they are presented to the user can vary across devices, or according to a style sheet. On a mobile telephone where screen space is scarce, both might be represented with menus, while on a larger screen both might be represented with selectable buttons. You are allowed to give a hint to what you want, or you may use a stylesheet to give precise styling, but if you don't, a device, or a style sheet, may make a choice for you.

So here is how you write the equivalent of the HTML Forms controls.

Simple Text Input

First name: <input type="text" name="firstname">

is written

<input ref="firstname"><label>First name:</label></input>

There is no need to indicate that it is text: in the absence of any other information, by default it is text (called string in XForms).

See later under 'initial values' for how to give any control an initial value.

Textarea

Message: <textarea name="message" rows="20" cols="80"></textarea>

is written

<textarea ref="message"><label>Message:</label></textarea>

Styling, such as the height and width here, is done using a style sheet. For instance, put this in your style sheet

textarea[ref="message"] { font-family: sans-serif;
                          height: 20em; width: 80em }

Although this mimics the HTML behavior, there is no requirement that you use a sans serif font, nor that you specify the width in rows and columns like this: you could use lengths, or percentages, or whatever:

textarea[ref="message"] { font-family: serif;
                          height: 2cm; width: 20% }

If you want all your textareas to have the same dimensions, you can use

textarea { font-family: sans-serif;
           height: 20em; width: 80em }

The easiest way to include a style sheet in your document is to add this at the beginning of the document:

<?xml version="1.0"?>
<?xml-stylesheet href="style.css" type="text/css"?>

where 'style.css' is the name of your stylesheet.

Radio Buttons

Radio buttons select one value from a number of alternatives:

Gender:
<input type="radio" name="sex" value="M"> Male
<input type="radio" name="sex" value="F"> Female

becomes

<select1 ref="sex">
   <label>Gender:</label>
   <item>
      <label>Male</label><value>M</value>
   </item>
   <item>
      <label>Female</label><value>F</value>
   </item>
</select1>

Bear in mind that this may be presented as any one of radio buttons, a (scrollable) select area, or a menu. You may include a hint appearance="full" on the <select1> to suggest that it should be presented as radio buttons. (Use appearance="compact" to suggest a select area and appearance="minimal" to suggest a menu).

The section on 'initial values' later says how to preselect a value.

Checkboxes

Checkboxes select zero or more from a list.

Flavors:
<input type="checkbox" name="flavors" value="v"> Vanilla
<input type="checkbox" name="flavors" value="s"> Strawberry
<input type="checkbox" name="flavors" value="c"> Chocolate

is written

<select ref="flavors" appearance="full">
   <label>Flavors:</label>
   <item>
      <label>Vanilla</label><value>v</value>
   </item>
   <item>
      <label>Strawberry</label><value>s</value>
   </item>
   <item>
      <label>Chocolate</label><value>c</value>
   </item>
</select>

The section on 'initial values' says how to pre-check values.

Depending on the presence of the multiple attribute in HTML, menus select one, or zero or more from a list of options. You either use <select1> to select a single choice, or <select> to select zero or more.

Month:
<select multiple name="spring">
      <option value="Mar">March</option>
      <option value="Apr">April</option>
      <option>May</option>
</select>

would be written:

<select ref="spring" appearance="minimal">
<label>Month:</label>
<item><label>March</label><value>Mar</value></item>
<item><label>April</label><value>Apr</value></item>
<item><label>May</label><value>May</value></item>
</select>

If multiple isn't present on the HTML select, then use select1 instead.

The section on 'initial values' says how to preselect values.

File Select

<form method="post" enctype="multipart/form-data" ...>
 ...
File: <input type="file" name="attachment">

is written

<submission method="form-data-post" .../>
...
<upload ref="attachment"><label>File:</label></upload> 

Passwords

Password: <input type="password" name="pw">

is written

<secret ref="pw"><label>Password:</label></secret>

Reset

Ten years of experience with HTML Forms has shown that hardly anyone actually uses reset buttons, and yet very many Web forms include them. A problem is that often the reset button with the text "Reset" is larger than the submission button that is often marked "OK", with the result that people accidently click on reset when they mean to click on OK, sometimes losing a lot of work (few if any browsers offer an undo). Therefore, while it is possible to create a reset button in XForms, it is deliberately harder to do, in order to discourage people unless they really want one:

<input type="reset">

is therefore written

<trigger>
   <label>Clear all fields</label>
   <reset ev:event="DOMActivate"/>
</trigger>

Buttons

Buttons have no predefined behavior, but have a behavior attached to them which is triggered when a relevant event occurs.

The button element

<input type="button" value="Show" onclick="show()">

can be written

<trigger><label>Show</label>
   <h:script ev:event="DOMActivate" type="text/javascript">show()</h:script>
</trigger>

or

<trigger ev:event="DOMActivate" ev:handler="#show">
    <label>Show</label>
</trigger>

where "#show" locates the element (for instance a script element) that implements the behavior:

<script id="show" ...>...

XForms has a number of built in actions that can be executed by a button; see the reset button above for an example.

The fact that the event attribute has a prefix, means that you have to add the following XML Namespace to the head:

xmlns:ev="http://www.w3.org/2001/xml-events"

Image Buttons

<input type="image" src="..." ...>

is written by putting an image into the <label> element:

<trigger...><label><h:img src="..." .../></label></trigger>

or by specifying it in a stylesheet

<trigger id="activate" ...>

with a stylesheet rule

trigger#activate {background-image: url(button.png);
                  background-repeat: none}

(Likewise for <submit>.)

Optgroup

Drink:
<select name="drink">
   <option selected value="none">None</option>
   <optgroup label="Soft drinks">
      <option value="h2o">Water</option>
      <option value="m">Milk</option>
      <option value="oj">Juice</option>
   </optgroup>
   <optgroup label="Wine and beer">
      <option value="rw">Red Wine</option>
      <option value="ww">White Wine</option>
      <option value="b">Beer</option>
   </optgroup>
</select>

is written

<select1 ref="drink">
   <label>Drink:</label>
   <item><label>None</label><value>none</value></item>
   <choices>
      <label>Soft drinks</label>
      <item><label>Water</label><value>h2o</value></item>
      <item><label>Milk</label><value>m</value></item>
      <item><label>Juice</label><value>oj</value></item>
   </choices>
   <choices>
      <label>Wine and beer</label>
      <item><label>Red wine</label><value>rw</value></item>
      <item><label>White wine</label><value>ww</value></item>
      <item><label>Beer</label><value>b</value></item>
   </choices>
</select1>

Grouping Controls

<fieldset>
   <legend>Personal Information</legend>
   Last Name: <input name="lastname" type="text">
   First Name: <input name="firstname" type="text">
   Address: <input name="address" type="text">
</fieldset>

is written

<group>
   <label>Personal Information</label>
   <input ref="lastname"><label>Last name:</label></input>
   <input ref="firstname"><label>First name:</label></input>
   <input ref="address"><label>Address:</label></input>
</group>

Note the consistent use of <label>.

Output Controls*

XForms has two controls that are not in HTML, output and range.

The output control allows you to include values as text in the document.

Your current total is: <output ref="sum"/>

or

<output ref="sum"><label>Total</label></output>

This can be used to allow the user to preview values being submitted.

You can also calculate values:

Total volume: <output value="height * width * depth"/>

(where height, width and depth are values collected by other controls.)

Range Controls*

This control allows you to specify a constraint on a value.

<range ref="volume" start="1" end="10" step="0.5"/>

A user agent may represent this as a slider or similar.

Hidden Controls

As you will see in the next section, there is no need for hidden controls in XForms.

Submitted Values

The attribute named ref on each control actually refers to a child of an instance element in the model, where the values are gathered before submission. If there is no instance element there (as in the search example above), then one is silently created.

Making the Submitted Values Explicit

Although it is perfectly allowable to let the system create your instance for you, there are reasons why it is a good idea to include one anyway, like this for the search example:

<model>
    <instance><data xmlns=""><q/></data></instance>
    <submission action="http://example.com/search"
                method="get" id="s"/>
</model>

From this you immediately see that the only data value submitted is called "q". The most obvious advantage of this is the documentation value of being able to see what is being submitted, but the system will now also check that when you say ref="q" that there really is a q in the instance.

Note that it is essential, for reasons we won't go into detail here, that you put the xmlns="" on your instance data, to tell the processor that the elements here are neither XHTML nor XForms elements.

(Note that we've used the tag <data> here, but you can choose any tag you like.)

Initial Values

For initialising controls including initialising checked boxes, and selected menu items etc., you just supply an instance with pre-filled values. For the search example:

<instance><data xmlns=""><q>Keywords</q></data></instance>

would pre-fill the text control with the word Keywords.

Similarly for the example in the checkboxes section, which looks like this:

<select ref="flavors" appearance="full">
   <label>Flavors:</label>
   <item>
      <label>Vanilla</label><value>v</value>
   </item>
   <item>
      <label>Strawberry</label><value>s</value>
   </item>
   <item>
      <label>Chocolate</label><value>c</value>
   </item>
</select>

You can preselect the vanilla and strawberry checkboxes like this:

<instance><data xmlns=""><flavors>v s</flavors></data></instance>

Similarly for the menus example, which looked like this:

<select ref="spring" appearance="minimal">
<label>Month:</label>
<item><label>March</label><value>Mar</value></item>
<item><label>April</label><value>Apr</value></item>
<item><label>May</label><value>May</value></item>
</select>

You can preselect March and April like this:

<instance><data xmlns=""><spring>Mar Apr</spring></data></instance>

And for the optgroup example:

<select1 ref="drink">
   <label>Drink:</label>
   <item><label>None</label><value>none</value></item>
   <choices>
      <label>Soft drinks</label>
      <item><label>Water</label><value>h2o</value></item>
      <item><label>Milk</label><value>m</value></item>
      <item><label>Juice</label><value>oj</value></item>
   </choices>
   <choices>
      <label>Wine and beer</label>
      <item><label>Red wine</label><value>rw</value></item>
      <item><label>White wine</label><value>ww</value></item>
      <item><label>Beer</label><value>b</value></item>
   </choices>
</select1>

Preselect the value none like this:

<instance><data xmlns=""><drink>none</drink></data></instance>

Hidden Values

The reason that XForms does not need hidden controls is that any values in the instance that haven't been bound to by a control are by definition not visible to the user. So if we want to add a hidden value results to the search form, we change the instance to:

<instance><data xmlns=""><q/><results>10</results></data></instance>

Getting Initial Values From Elsewhere*

You don't have to specify the initial instance in the document itself, because you can load it from an external resource, like this:

<instance src="http://example.org/forms/templates/t21.xml"/>

and the document t21.xml can then contain your data, like

<data><w>640</w><h>480</h><d>8</d></data>

(You don't need the xmlns="" in external instances, though it doesn't do any harm either.)

'Editing' any XML document*

Loading external instances gives you immense power. This is because the ref attribute on the forms controls doesn't just let you select an identifier as HTML's name does, but in fact can be any XPath expression. XPath lets you select any element or attribute in an XML document.

This means that once you have learnt XPath, you can bring in any XML document as instance, even an XHTML document, bind controls to it, and submit it. For instance to bind to the <title> element in an XHTML document, you can use

<input ref="/h:html/h:head/h:title">...

(i.e. the title element within the head element within the html element, all in the XHTML namespace), or

<input ref="/h:html/h:body/@class">...

which is the class attribute on the body element.

For example, suppose a shop has very unpredictable opening hours (perhaps it depends on the weather), and they want to have a Web page that people can go to to see if it is open. Suppose the page in question has a single paragraph in the body:

<p>The shop is <strong>closed</strong> today.</p>

Well, rather than teaching the shop staff how to write HTML to update this, we can make a simple form to edit the page instead:

<model>
   <instance      src="http://www.example.com/shop/status.xhtml"/>
   <submission action="http://www.example.com/shop/status.xhtml"
               method="put" id="change"/>
</model
...
<select1 ref="/h:html/h:body/h:p/h:strong">
<label>The shop is now:</label>
<item><label>Open</label><value>open</value></item>
<item><label>Closed</label><value>closed</value></item>
</select1>
<submit submission="change"><label>OK</label></submit>

Note that for this to work, the page in question that is being changed must be correct XHTML, (and not HTML, since only XHTML is an XML document), and your server must accept the "put" method (not all servers do). However, if the XHTML document in question is in a file on the local machine, then you can get the instance from the file, and write it back with a submit. See below.

Submitting

Multiple Submissions*

HTML only allows you to submit the data to one server, in a single way.

XForms allows you to have different submit controls binding to different submission elements in the head to submit the data to different servers, or in different ways.

For instance, the search example could allow the user to submit the search string to different search engines:

<model>
   <instance><data xmlns=""><q/></data></instance>
   <submission action="http://example.com/search"
               method="get" id="com"/>
   <submission action="http://example.org/search"
               method="get" id="org"/>
</model>

and then in the body:

<submit submission="org"><label>Search example.org</label></submit>
<submit submission="com"><label>Search example.com</label></submit>

Submission Methods

Just as with HTML there are a number of ways to submit the data. In HTML how to submit is expressed in two attributes, method and enctype; in Xforms it is expressed in method only:

HTML and XForms Equivalent Submission Methods
HTML XForms
method="get" method="get"
method="post"
enctype="application/x-www-form-urlencoded"
method="urlencoded-post"
method="post"
enctype="multipart/form-data"
method="form-data-post"

There are some new ways of submission; the most interesting are method="post" which posts the results as an XML document, and method="put" which puts the results as an XML document. An interesting use of this is something like:

<submission action="file:results.xml" method="put"/>

which saves your results to the local filestore by using the file: scheme.

Since, as shown above, you can have more than one submission per form, this means that for a large form, you could have separate 'save to disk' and 'submit' buttons.

Life after Submit*

The default when values have been submitted is for the result returned by the server to replace the whole document, just as with HTML. However, there are other options, specified with the attribute replace on the submission element. The value replace="instance" replaces only the instance, and replace="none" leaves the form document as-is without replacing it.

For instance, for an address-change form for a bank, you can provide two buttons, one to prefill the form with name and address based on the account number, and one to submit the changed results:

<model>
    <instance><data xmlns="">
        <accountnumber/><name/><address/>
    </data></instance>
    <submission method="get" action="http://example.com/prefill"
                id="prefill" replace="instance"/>
    <submission method="get" action="http://example.com/change"
                id="change" replace="none"/>
</model>
...
<input ref="accountnumber"><label>Account Number</label></input>
<submit submission="prefill"><label>Find</label></submit>
<input ref="name"><label>Name</label></input>
<textarea ref="address"><label>Address</label></textarea>
<submit submission="change"><label>Submit</label></submit>

The 'find' button will replace the instance with a new instance containing the details of the person with the account number, which you can then change; the 'submit' button will then send the changed instance back, leaving the form as-is in the browser to allow further changes or to input a new account number to prefill.

Controlling Controls

In HTML you can specify that controls are disabled, or read-only but the only way you can change the property is with scripting.

XForms offers easy ways to control these properties, but has other properties you can specify as well:

Note that in XForms it is the collected value that has the property, not the control, but the property shows up on all controls bound to the value.

These properties use a <bind> element that goes in the <model>. To use bind, you must have an explicit <instance> element.

Disabled Controls

To disable controls you use the relevant property. For instance, to say that the credit card number only needs to be filled in if the person is paying by credit, you can write:

<model>
   <instance><data xmlns="">
      <amount/><method/><cc/><expires/>
   </data></instance>
   <bind nodeset="cc" relevant="../method='credit'"/>
   <bind nodeset="expires" relevant="../method='credit'"/>
</model>

This states that the fields cc and expires are only relevant when method has the value credit, and will therefore be disabled for other values of method. You have to say "../method" rather than just method, because in a bind you are talking about the thing referred to in the nodeset (which might be a structured element itself). It is as if you have done a 'change directory' to that element. If you said just "method", it would refer to a child element of cc or expires. You can also use absolute addressing, like /data/method, which would have the same effect as ../method in this case.

A browser is free to decide how disabled controls are presented (and it may also allow you to specify in a stylesheet how they should look), but typically they will be grayed out in the normal way.

The controls could be written like this (but note that there is no indication that they may get disabled: that is inherited from the value they refer to):

<select1 ref="method"><label>Method of payment:</label>
   <item><label>Cash</label><value>cash</value></item>
   <item><label>Credit card</label><value>credit</value></item>
</select1>
<input ref="cc"><label>Card number:</label></input>
<input ref="expires"><label>Expiry date:</label></input>

If we used a structured instance, we could simplify this:

<model>
   <instance><data xmlns="">
      <amount/><method/>
      <cc>
        <number/><expires/>
      </cc>
   </data></instance>
   <bind nodeset="cc" relevant="../method='credit'"/>
</model>

and the controls then reference the children of 'cc':

<input ref="cc/number"><label>Card number:</label></input>
<input ref="cc/expires"><label>Expiry date:</label></input>

although grouping can be used to reset the context of the refs:

<group ref="cc">
   <input ref="number"><label>Card number:</label></input>
   <input ref="expires"><label>Expiry date:</label></input>
</group>

Readonly Controls

Similarly to relevant, you can specify a condition under which a value is read-only. For instance:

<model>
   <instance><data xmlns="">
      <variant>basic</variant><color>black</color>
   </data></instance>
   <bind nodeset="color" readonly="../variant='basic'"/>
</model>

This example says that the default value of color is black, and can't be changed if variant has the value basic.

Required Controls*

A useful new feature in XForms is the ability to state that a value must be supplied before the form is submitted. The simplest case is just to say that a value is always required. For instance, with the search example:

<model>
   <instance><data xmlns=""><q/></data></instance>
   <bind nodeset="q" required="true()"/>
   <submission .../>
</model>

but like the readonly and relevant attributes, you can use any XPath expression to make a value conditionally required:

<bind nodeset="state" required="../country='USA'"/>

which says that the value for state is required when the value for country is "USA".

It is up to the browser to decide how to tell you that a value is required, but it may also allow you to define it in a stylesheet.

Constraint Property*

This property allows you to add extra constraints to a value. For instance:

<bind nodeset="year" constraint=". &gt; 1970"/>

constrains the year to be after 1970. Note the XPath use of "." to mean "this value". (">" has to be written as &gt; because of XML rules, but you should be used to that already).

Calculate Property*

It is possible to indicate that a value in the instance is calculated from other values. For instance:

<bind ref="volume" calculate="../height * ../width * ../depth"/>

When a value is calculated like this, it automatically becomes readonly.

There are a number of functions available, including arithmetic, string manipulation, date handling, and conditionals using 'if'.

Types*

Another useful new feature is the ability to give a value a type. The browser can then check that the values match the required type.

For instance, if the search example is actually only for searching for numbers (for instance for searching in a bug database), then we only have to add:

<bind nodeset="q" type="xsd:integer"/>

This will prevent the value being submitted unless it is an integer.

(You then need to add xmlns:xsd="http://www.w3.org/2001/XMLSchema" to the root element.)

If you want to collect the URL of someone's homepage, then you can specify

<bind nodeset="homepage" type="xsd:anyURI"/>

You will find that some user agents do special things when they know the data type of a value. For instance, when they know that the value is a date, they pop up a date picker rather than require you to type in the characters of the date.

There are a number of useful built-in types you can use, including:

Combining Properties

If you have several binds referring to the same value, you can combine them:

<bind nodeset="q" type="xsd:integer" required="true()"/>

More than one form in a document

For more than one form in a document, you need one model per form, but then you need to identify which form each control refers to. You do this with an id attribute on each model, and a model attribute on each control:

<model id="search">
   <instance><data xmlns=""><q/></data></instance>
   <submission id="s" .../>
</model>
<model id="login">
   <instance><data xmlns=""><user/><passwd/></data></instance>
   <submission id="l" .../>
</model>
...
<input model="search" ref="q"><label>Find</label></input>
<submit submission="s"><label>Go</label></submit>
...
<input model="login" ref="user"><label>User name</label></input>
<secret model="login" ref="passwd"><label>Password</label></secret>
<submit submission="l"><label>Log in</label></submit>

Bind instead of Ref

If there is a bind in the model, you can refer to that from the control instead of directly to the instance value. This allows you to change the details of how the instance is structured without having to change the controls. It also means you don't have to specify which model is involved:

<model>
   <instance><data xmlns=""><q/></data></instance>
   <submission id="s" .../>
   <bind id="query" nodeset="q" required="true()"/>
</model>
...
<input bind="query"><label>Find</label></input>

(Note that the bind attribute is a reference to an id on a bind element; it is not an XPath expression.)

Features Not Handled Here

As mentioned in the introduction, this is not a full tutorial on XForms. Here are the main features not treated here:

These are all treated in detail in part 2.