W3C

XForms: A Tutorial

Steven Pemberton, W3C/CWI

Version date: 2020-10-06

Introduction

XForms is a markup language for forms and applications on the Web. This document is a tutorial introduction to XForms; although it assumes knowledge of forms in HTML and shows how to convert HTML forms to their XForms equivalent it should still be readable for people who do not know HTML. 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. An earlier version of this tutorial introduced XForms 1.0. This version is updated for XForms 1.1.

Table of Contents

*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. In this case the minimum you need to put in the head is:

<model>
   <submission action="http://example.com/search"
               method="get"/>
</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><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"/>
    </model>
</h:head>
<h:body>
    <h:p>
    <input ref="q"><label>Find</label></input>
    <submit><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:xf="http://www.w3.org/2002/xforms">
<head>
    <title>Search</title>
    <xf:model>
        <xf:submission action="http://example.com/search"
                       method="get"/>
    </xf:model>
</head>
<body>
    <p>
        <xf:input ref="q"><xf:label>Find</xf:label></xf:input>
        <xf:submit><xf:label>Go</xf:label></xf:submit>
    </p>
</body>
</html>

Another technique is to swap default namespaces as needed, like this:

<html xmlns="http://www.w3.org/1999/xhtml"
<head>
    <title>Search</title>
    <model xmlns="http://www.w3.org/2002/xforms">
        <submission action="http://example.com/search"
                    method="get"/>
    </model>
</head>
<body>
    <group xmlns="http://www.w3.org/2002/xforms">
        <input ref="q"><label>Find</label></input>
        <submit><label>Go</label></submit>
    </group>
</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 (or at least, it ought to be; however, some implementations require you to leave the HTML elements unprefixed, and the XForms elements prefixed).

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). Try it:

(Source)

By default the data is updated when you leave the control. Adding the attribute incremental="true" to any control means that the data is updated as you type:

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

(Source)

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

Output Controls*

The above two examples used, apart from the input controls, a control that is not in HTML: output. This 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 filled in and can also calculate values:

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

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

(Source)

Adding the attribute incremental="true" to the input controls above causes the calculated values to be updated as you type:

(Source)

If you add mediatype="image/*" to an output control, the value will be interpreted as a URL and displayed as an image:

<output ref="photo" mediatype="image/*"/>

There will be examples of this later

Textarea

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

is written

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

(Source)

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

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

Although this mimics the HTML behavior, there is no requirement that you use a monospace 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 }

You include a stylesheet in your document in the usual way (for instance using <link> or <style> in HTML).

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). Here is an example - note that since they are all bound to the same data value, if you change one, they all change to match:

(Source)

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>

Similarly to select1, you can use the appearance attribute to effect how it is displayed:

(Source)

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>

This example uses a secret control and an extra control to optionally show what has been typed:

(Source)

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>Reset all fields</label>
   <reset ev:event="DOMActivate"/>
</trigger>

(Source)

One important difference to note with the HTML version is that fields are reset to their initial value, and are not just blanked out (you can see that in the above example if you change the values and then press on reset).

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"

You will find a fuller explanation of the event markup in part 2.

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.

Image Buttons

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

can be written in several ways, such as 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}

or by using an XForms <output>:

<trigger>
   <label><output mediatype="image/*" value="'http://www.example.com/image.png'"/></label>
</trigger>

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

Range Controls*

The one other control, apart from output, that is not in HTML is range. This control allows you to specify a constraint on a value.

<range ref="volume" start="1" end="11" 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"/>
</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 the tag <data> has been used here, but you can choose any tag you like.)

Initial Values

For initializing controls including initializing 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 you want to add a hidden value results to the search form, you 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, you can make a simple form to edit the page instead:

<model>
   <instance      src="shop/status.xhtml"/>
   <submission action="shop/status.xhtml"
               method="put"/>
</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><label>OK</label></submit>

(This example really does load the above XHTML file, but the save won't work:)

(Source)

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>

Note how which submission to use is identified with the 'id' attribute. The first submission element in the model is the default one, so it's also possible to write:

<model>
   <instance><data xmlns=""><q/></data></instance>
   <submission action="http://example.com/search"
               method="get"/>
   <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><label>Search example.com</label></submit>

but not that a risk of doing this is that you then can't move the submission elements around to change their order.

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.

It will look like this (this is a mock-up, where the changed value is not submitted, but it gives you the idea):

(Source)

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.

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>

Try it:

(Source)

This can be simplified by using a structured instance:

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

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, or hidden entirely. The stylesheet rule could look like:

input::disabled {display: none}

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. Try it:

(Source)

(This example will be changed below so that the value of color is also reset to black if the variant is reset to basic. See the calculate property shortly).

The stylesheet rule for a readonly element is

input::read-only {...}

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". Try it:

(Source)

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, such as:

input::required { border: thin red solid }

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

You can combine values, such as:

<bind nodeset="death" constraint=". &gt;= ../birth"/>

Try it:

(Source)

A control, apart from the label can also contain an alert that explains what the restrictions are on a value being collected:

<input ref="death"><label>Year of death</label>
    <alert>Death year may not be earlier than birth</alert>
</input>

Calculate Property*

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

<bind ref="years" calculate="../death - ../birth"/>

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

(Source)

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

The read-only example above can be adapted to use a constraint to ensure the default value of color applies for basic models:

<model>
   <instance><data xmlns="">
      <variant>deluxe</variant><color>yellow</color>
   </data></instance>
   <bind nodeset="color"
         readonly="../variant='basic'"
         calculate="if(../variant='basic', 'black', .)"/>
</model>

This says that if the variant is basic, then color is set to black, otherwise color keeps the value it has got.

(Source)

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), you only have to add:

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

This will prevent the value being submitted unless it is an integer. Try it (this example also uses an alert element):

(Source)

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

<bind nodeset="homepage" type="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. Like this:

<bind nodeset="when" type="date"/>
 ...
<input ref="when"><label>Date:</label><input>

(Source)

Similarly, if a value is a boolean, it gets represented as a check box:

<bind nodeset="agree" type="boolean"/>
 ...
<input ref="agree"><label>I agree to all conditions</label></input>

(Source)

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

All these types are built in to XForms. If you need to use types defined elsewhere, you can use a prefix in the usual way:

type="xsd:float"

(as usual adding the declaration for the prefix xsd).

Combining Properties

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

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

For instance, a credit-card number is a data type, but credit card numbers also have a sort of check-sum built in, which is represented by a constraint:

<bind nodeset="cc" type="card-number" constraint="is-card-number(.)"/>

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>

More than one instance in a model

There are times when you need more than one instance. For instance, it can be useful in computations to have one instance that contains the values for the current tax regulations, and another instance to collect the values for a particular person. This is easy, since you can have as many instances as you want in a model:

<model>
    <instance><data xmlns=""><name/><age/><salary/><taxrate/></data></instance>
    <instance id="tax" src="tax.xml"/>
    <instance id="currencies" src="currencies.xml"/>
    ...
</model>

To identify which instance you mean, you use the instance function:

<input ref="instance('tax')/minimumwage">...
<output ref="instance('currencies')/eur">...

The first instance in a model is the default, and 'unadorned' references always refer to that:

<input ref="age">...

The instance function works in calculations too:

<bind nodeset="taxrate"
      calculate="if(../salary &gt; instance('tax')/limit, 
                    instance('tax')/high, 
                    instance('tax')/low)"

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.