XForms basics

Learn the essentials for creating the next generation of forms

XForms provides a host of new capabilities for Web authors and developers who want to create Web forms that include rich interactive experiences while still maintaining many of the familiar aspects of creating forms in HTML. This article explains the basics of creating an XForms form, including the structure of the form itself; basic controls, or fields; and the most common submission options.

Share:

Nicholas Chase (ibmquestions@nicholaschase.com), Freelance writer, Backstop Media

Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, an Oracle instructor, and the Chief Technology Officer of an interactive communications company. He is the author of several books, including XML Primer Plus (Sam's).



10 October 2006

Also available in Chinese Russian

Introduction

Web forms have been around for a long time, but there's only so much you can do with them. XForms provides a great deal more capability, including enhanced interactivity and more submission options, but before you can get into the bells and whistles, you need to know the basics of putting together an XForms form.

Getting started

The first thing you're going to need is a browser capable of displaying XForms. For this article, you will be using Firefox, along with the XForms extension, available at Mozilla.org. (Note that it is marked as "not yet meant for end users," but at the time of this writing it seems quite stable.) If you prefer Microsoft® Internet Explorer, you can download Formsplayer from here. You'll need to make some minor changes to the top of the file to load Formsplayer, and your files will need to use .htm instead of .xhtml, as you'll be using for the Firefox forms, but other than that they should work just fine. Check out the sample code included in this article to see the differences.

This article assumes that you are familiar with the general concepts of XML.


Creating a basic form

Consider the example of a form designed to gather information about a user's favorite composer. In an HTML form, you would simply include form fields on the page within a form element. An XForms form is similar, but the structure is a bit different. You can see a simple form in Listing 1.

Listing 1. the basic form
<?xml version="1.0" encoding="ASCII"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xforms="http://www.w3.org/2002/XForms">
<head>
<title>Describe a composer</title>

<xforms:model id="model_composers">

    <xforms:instance xmlns="">
        <composers>
           <composer>
               <name></name>
               <genre></genre>
               <accessibility></accessibility>
               <difficulty></difficulty>
               <totalscore></totalscore>
               <examples>
                  <example></example>
                  <example></example>
                  <example></example>
               </examples>
            </composer>
        </composers>
    </xforms:instance>

    <xforms:submission id="submit_model_composers"
      action="http://XFormstest.org/cgi-bin/showinstance.sh" method="post"/>

</xforms:model>

</head>
<body>
...

The first part of the form is the model. The model defines the data to be included in the form and specifies what happens to that data when the user submits it. In this case, a simple XML document -- called the instance -- has been created to hold the data, and the submission element specifies that when that data gets submitted, it should be sent to http://xformstest.org/cgi-bin/showinstance.sh. As you'll see in a moment, this destination simply echoes back the data you submit. The next step is to create the actual form elements themselves (see Listing 2).

Listing 2. The form elements
...
    </xforms:instance>
    <xforms:submission id="submit_model_composers"
      action="http://XFormstest.org/cgi-bin/showinstance.sh" method="post"/>
</xforms:model>

</head>
<body>

<xforms:input ref="/composers/composer/name">
    <xforms:label>Name: </xforms:label>
</xforms:input>
<br />
<xforms:input ref="/composers/composer/genre">
    <xforms:label>Genre: </xforms:label>
</xforms:input>
<br />
<xforms:input ref="/composers/composer/accessibility">
    <xforms:label>Accessibility: </xforms:label>
</xforms:input>
<br />
<xforms:input ref="/composers/composer/difficulty">
    <xforms:label>Difficulty: </xforms:label>
</xforms:input>
<br />
<xforms:input ref="/composers/composer/totalscore">
    <xforms:label>Totalscore: </xforms:label>
</xforms:input>
<br />
<xforms:repeat
    id="repeat_example_model_composers"
    nodeset="/composers/composer/examples/example">
    <xforms:input ref=".">
        <xforms:label>Example: </xforms:label>
    </xforms:input>
</xforms:repeat>

<xforms:submit submission="submit_model_composers">
    <xforms:label>Submit</xforms:label>
</xforms:submit>

</body>
</html>

The first few fields are fairly straightforward. Text input fields have been created using the input element, and the ref attribute has been used to specify the node in the instance document to which this "control" corresponds. In other words, when the user enters a name, such as Mozart, into the name control, that information automatically becomes the content of the /composers/composer/name element. Each control also has a label, which does exactly what it sounds like and provides a label in the browser window so the user knows what he or she is looking at.

At the bottom of Listing 2 a repeat element has been added. This element selects a specific group of nodes, in this case the example elements, and executes its contents once for each of them. Notice that the repeat element has as its contents another input control, but this time the ref attribute refers to the current node in the nodeset.

If you load this form in the browser, you should see something familiar, as you can see in Figure 1.

Figure 1. The basic form
The basic form

Notice that the labels line themselves up nicely just before each of the form fields. Make sure to include any required spaces in the label.

Now let's look at what happens when you actually enter data into the form.

The basic submission

As mentioned earlier, the ref attribute links a control to a node in the instance document. You can see this in action if you fill out the form, as shown in Figure 2, and select the Submit button.

Figure 2. Filling out the form
Filling out the form

You can then submit the form. In this case, you have done nothing to specify anything special about the data being submitted. In the case of an HTML form, the data comes through as name-value pairs, but this is not an HTML form. The default for XForms forms is to submit the actual XML instance as the contents of a POST request. The destination specified takes that information and simply echoes it back, so you can see the results in Figure 3.

Figure 3. The results
The results

That takes care of the very basics, but before moving on, let's take care of a little bit of cleanup.

Moving the instance to a separate file

In many of the examples in the series of tips that accompany this article, you will see that the instance does not actually have to be part of the form -- at least not directly. You can also separate the XML instance into a separate document and then reference the document from the instance element (see Listing 3).

Listing 3. Segregating the data
...
<xforms:model id="model_composers">
    <xforms:instance src="composer.xml">
    </xforms:instance>
    <xforms:submission id="submit_model_composers"
      action="http://XFormstest.org/cgi-bin/showinstance.sh" method="post"/>
</xforms:model>
...

This separation makes the form a lot easier to deal with, and also makes it easier to change the instance data as necessary.


Additional control types

Now that you have the very basics, let's look at some of the other types of controls you can add to a form.

Secret

In HTML, one commonly used field is the "password" field, which isn't actually secure, but does obscure what the user is typing so no one can observe it over their shoulder. Of course, they can be used for other things besides passwords, so in XForms it is called the secret control. For example, perhaps you want people to guess who the composer is based on the clues (see Listing 4).

Listing 4. The secret control
...
<body>

<xforms:secret ref="/composers/composer/name" 
                                 model="model_composers">
       <xforms:label>Name: </xforms:label>
</xforms:secret>
<br />
<xforms:input ref="/composers/composer/genre" model="model_composers">
...

Now if the form is rendered, you can see that the typing for the name field is no longer visible, as you can see in Figure 4.

Figure 4. Obscuring data
Obscuring data

Other controls are more about functionality than appearance.

Range

One control that does not have a counterpart in HTML is the range control. This is a control that appears as a "slider" that the user can move back and forth to select a value. You can control the start value, end value, and size of the intervals (see Listing 5).

Listing 5. The range control
...
<xforms:input ref="/composers/composer/genre">
    <xforms:label>Genre: </xforms:label>
</xforms:input>
<br /> <br />
<xforms:range start="-10" end="10" step="1" 
              ref="/composers/composer/accessibility">
   <xforms:label>Accessibility: <br /></xforms:label>
</xforms:range>
<br /> <br />
<xforms:range  start="-5.0" end="5.0" step="0.5" 
                 ref="/composers/composer/difficulty">
   <xforms:label>Difficulty: <br /></xforms:label>
</xforms:range>
<br /> <br />
<xforms:input ref="/composers/composer/totalscore"
   >
    <xforms:label>Totalscore: </xforms:label>
</xforms:input>
...

Note that you do not have to make your ranges symmetrical, as has been done here. The numbers you choose are completely arbitrary, as is the size of the step. If you reload the page, you can see the sliders in place as in Figure 5.

Figure 5. The range control
The range control

The data selected by a user using a range is simply a number, and is added to the instance document as though the user had typed in directly. You can test this by submitting the form and looking at the instance document.

Selections

HTML also includes the ability to offer a number of enumerated options. In HTML, you can create a field that allows for either single or multiple choices, but you have to decide beforehand what it will look like. For example, you can add series of checkboxes, or a series of radio buttons, or a pulldown menu. In XForms, you simply specify that you want the user to be able to make a selection, and let the rendering engine handle the rest (see Listing 6).

Listing 6. The select control
...
<xforms:input ref="/composers/composer/name">
    <xforms:label>Name: </xforms:label>
</xforms:input>
<br />
<xforms:input ref="/composers/composer/genre">
    <xforms:label>Genre: </xforms:label>
</xforms:input>
<xforms:select ref="/composers/composer/genre" appearance="full">
    <xforms:label>Genre: </xforms:label>
    <xforms:item>
        <xforms:label>Baroque</xforms:label>
        <xforms:value>B</xforms:value>
    </xforms:item>
    <xforms:item>
        <xforms:label>Classical</xforms:label>
        <xforms:value>C</xforms:value>
    </xforms:item>
    <xforms:item>
        <xforms:label>Neo-Classical</xforms:label>
        <xforms:value>NC</xforms:value>
    </xforms:item>
    <xforms:item>
        <xforms:label>Modern</xforms:label>
        <xforms:value>M</xforms:value>
    </xforms:item>
    <xforms:item>
        <xforms:label>Pop</xforms:label>
        <xforms:value>P</xforms:value>
    </xforms:item>
</xforms:select>
    
<xforms:range start="-10" end="10" step="1" 
              ref="/composers/composer/accessibility">
   <xforms:label>Accessibility: <br /></xforms:label>
</xforms:range>
...

In this case, a number of different items have been added to choose from, specifying for each one a label (the part that's visible to the user) and a value (the part that's actually submitted as part of the data). You can see this in action if you reload the form (see Figure 6).

Figure 6. The select list
The select list

A couple of things to notice here. First, notice that both the Genre input box and the select list reference the same node in the instance document. Because of this, when you check one of the boxes, the value for that box is added to the genre element, and appears in the input box.

Second, notice that checkboxes were not specified, but that's what is showing. What was specified is an appearance of full. In most cases, that will give you checkboxes for a select list. You can also specify the appearance as compact (see Listing 7).

Listing 7. Changing the appearance of the select list
...
<xforms:input ref="/composers/composer/genre">
    <xforms:label>Genre: </xforms:label>
</xforms:input>
<xforms:select ref="/composers/composer/genre" appearance="compact">
    <xforms:label>Genre: </xforms:label>
    <xforms:item>
        <xforms:label>Baroque</xforms:label>
        <xforms:value>B</xforms:value>
...

This changes the appearance of the select list, as you can see in Figure 7.

Figure 7. Changing the select list
Changing the select list

Note that the control is no longer rendered as a "block" element, automatically placed on its own line. Functionally, this behaves just as a multiple select list does in HTML.

The XForms specification also provides an appearance of "minimal," but in Firefox this looks the same as compact.

How a browser renders these is entirely up to the browser. This is one of the strengths of XForms, because it allows devices to do what they need to to get the point across. For example, a cell phone might display the select list in an entirely different way. This is one of the advantages of separating data from presentation.

This is all very nice, but what if you do not want the user to be able to select more than one choice? For example, what if you wanted radio buttons instead of checkboxes? You can achieve this using the select1 control, rather than the select control (see Listing 8).

Listing 8. The select1 control
...
<xforms:input ref="/composers/composer/genre">
    <xforms:label>Genre: </xforms:label>
</xforms:input>
<xforms:select1 ref="/composers/composer/genre" appearance="full">
    <xforms:label>Genre: </xforms:label>
    <xforms:item>
        <xforms:label>Baroque</xforms:label>
        <xforms:value>B</xforms:value>
    </xforms:item>
...
</xforms:select1>

<xforms:range start="-10" end="10" step="1" 
ref="/composers/composer/accessibility">
    <xforms:label>Accessibility: <br /></xforms:label>
</xforms:range>
...

The data is the same, but you can see the difference when you render the form (see Figure 8).

Figure 8. The select1 control
The select1 control

The XForms specification includes additional controls, such as the file upload control, but these are the ones that are used on a regular basis.


Setting values on controls

Another functionality common to forms is the setting of values, usually when the form is first loaded, but sometimes in the course of using a form. Let's take a look at how to make that happen within an XForms form.

Using initial values

You have already seen how adding information to form controls adds it to the instance. But in fact, this exchange works both ways. Information you add to the instance gets added to the controls on the form (see Listing 9).

Listing 9. Information in the instance
...
<xforms:model id="model_composers">

<xforms:instance xmlns="">
<composers>
   <composer>
      <name>Wolfgang Amadeus Mozart</name>
      <genre>C</genre>
      <accessibility>9</accessibility>
      <difficulty>9</difficulty>
      <totalscore>18</totalscore>
      <examples>
         <example>A little night music</example>
         <example>Twinkle, twinkle, little star</example>
         <example>Don Giovanni</example>
      </examples>
   </composer>
</composers>
</xforms:instance>

<xforms:submission id="submit_model_composers"
     action="http://XFormstest.org/cgi-bin/showinstance.sh" method="post"/>

</xforms:model>
...

Here you see information a little bit different from what the form previously contained, but if you load the form, you will see it on the page (see Figure 9).

Figure 9. Data from the instance
data from the instance

So anything you put in the instance is reflected in the controls, and vice versa. But XForms also gives you another option for making this connection.

Binding values

So far, you have seen only the ability to refer to a specific node within the instance. XForms also gives you the opportunity to explicitly "bind" to a particular node set. For example, you could create an ID by which to refer to a particular node (see Listing 10).

Listing 10. Creating a binding
<?xml version="1.0" encoding="ASCII"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xforms="http://www.w3.org/2002/XForms">
<head>
<title>Describe a composer</title>

<xforms:model id="model_composers">
    <xforms:instance xmlns="">
...
    </xforms:instance>
    <xforms:submission id="submit_model_composers"
      action="http://XFormstest.org/cgi-bin/showinstance.sh" method="post"/>
        <xforms:bind id="total" nodeset="/composers/composer/totalscore"/>

</xforms:model>

</head>
<body>

<xforms:input ref="/composers/composer/name">
    <xforms:label>Name: </xforms:label>
</xforms:input>
...
<xforms:range  start="-10.0" end="10.0" step="0.5" 
                   ref="/composers/composer/difficulty">
   <xforms:label>Difficulty: <br /></xforms:label>
</xforms:range>

<br /> <br />

<xforms:input bind="total">
    <xforms:label>Totalscore: </xforms:label>
</xforms:input>

<br />
<xforms:repeat
...

Notice that the Totalscore control does not refer to a specific node, but rather to a specific finding, as specified by its ID value. The form defines the binding itself in the model. This way, when you load the form, XForms still knows where to get the Totalscore value (see Figure 10).

Figure 10. Using the bind value
using the bind value

This capability is useful for abstracting the form; for example, in a large form, you can create bindings for each piece of data, and then you can change the structure of the instance without having to change the entire form; simply change the node sets in each binding.

Using calculated values

But perhaps the most useful function of bindings is to create calculated values. For example, you can create a situation in which the accessibility and difficulty values are automatically added to create Totalscore (see Listing 11).

Listing 11. Creating a calculated value
...
</xforms:instance>
    <xforms:submission id="submit_model_composers"
      action="http://XFormstest.org/cgi-bin/showinstance.sh" method="post"/>
        
    <xforms:bind id="total" nodeset="/composers/composer/totalscore" 
       calculate="/composers/composer/accessibility + 
                                  /composers/composer/difficulty"/>

</xforms:model>
...

Now if you load the form, you'll find that changing either the accessibility or difficulty values automatically changes the Totalscore value (see Figure 11).

Figure 11. Adding values
adding values

Submitting the form

You have already seen that typical submission of an XForms form involves sending the entire instance to the server. But that does not always have to be the case.


Submitting part of the form

One variation on XForms submission is to send only a small part of the instance. For example, you can instruct the form to submit only the example element (see Listing 12).

Listing 12. submitting only the examples
...
            </examples>
         </composer>
      </composers>

   </xforms:instance>
    
   <xforms:submission id="submit_model_composers" 
                         ref="/composers/composer/examples"
                         action="http://localhost/XForms.php"
                         method="post"/>
                         
   <xforms:bind id="total" nodeset="/composers/composer/totalscore" 
        calculate="/composers/composer/accessibility + 
                              /composers/composer/difficulty" />
</xforms:model>
...

Now if you submit the form, you will see that only the part of the instance specified in the ref attribute gets submitted (see Figure 12).

Figure 12. Submitting only part of the instance
submitting only part of the instance

Another variation is to submit the instance without replacing the entire page.


Replacing part of the instance

One big advantage of XForms over regular HTML forms is the ability to send a submission and receive the data back as XML, which can then be added to the instance and, as you have seen, to the existing controls on the page. Note that unless you adjust the security of your browser, the response must be coming from the same domain name from which the form was originally downloaded. For example, if you download page http://www.nicholaschase.com/composers.xhtml and you want the return submission to populate the instance with this form, the submission had better have a URL that begins with http://www.nicholaschase. That means that you cannot just load the form locally. Included with the sample forms for this article is a PHP script that simply returns the data. You can use it to test this next section.

Getting the form to replace the instance rather than the page is a simple matter of adding an attribute to the submission (see Listing 13).

Listing 13. Replacing the instance
...
    </xforms:instance>
    
           <xforms:submission id="submit_model_composers" 
                         ref="/composers/composer/examples"
                         replace="instance"
                         action="http://localhost/XForms.php"
                         method="post"/>
                         
    <xforms:bind id="total" nodeset="/composers/composer/totalscore" 
        calculate="/composers/composer/accessibility + 
                                    /composers/composer/difficulty" />
</xforms:model>

</head>
<body>
...
<br />
<xforms:repeat
    id="repeat_example_model_composers"
    nodeset="/composers/composer/examples/example">
    <xforms:input ref=".">
        <xforms:label>Example: </xforms:label>
    </xforms:input>
</xforms:repeat>

<xforms:repeat
    id="repeat_example_model_composers"
    nodeset="/examples/example">
    <xforms:input ref=".">
        <xforms:label>Submitted Example: </xforms:label>
    </xforms:input>
</xforms:repeat>

<xforms:submit submission="submit_model_composers">
    <xforms:label>Submit</xforms:label>
</xforms:submit>

</body>
</html>

Note that a second repeat element has been added that will only appear if there are /examples/example nodes in the document. For this reason, they will not appear when you first load the document, but after you submit, you will see them clearly (see Figure 13).

Figure 13. The submitted instance
The submitted instance

Before wrapping it up, there's one more thing you should know.


Back to basics: A traditional Web form

So far a lot of things that make XForms different from HTML forms have been looked at, but what if you want to use an XForms form but submit to an old-style script? Fortunately, it's easy to tell XForms to submit data in the old name-value style (see Listing 14).

Listing 14. Submitting traditional data
...
<xforms:model id="model_composers">
  <xforms:instance id="instance_model_composers" src="composer.xml"/>
                       
  <xforms:submission id="submit_model_composers" 
                         action="http://localhost/XForms.php"
                         method="get"
                         encoding="application/x-www-form-urlencoded"/>
                         
    <xforms:bind id="total" nodeset="/composers/composer/totalscore" 
        calculate="/composers/composer/accessibility + 
                                      /composers/composer/difficulty" />
</xforms:model>
...

Note that reusing the GET method rather than the POST method, because that is how XForms knows to put the data in the URL itself, rather than the request. Also, the encoding attribute tells it to create the name-value pairs. This way, if you submit the form, you will see that there is no information on the page -- a simple output statement was added to prevent errors -- but that information is now in the URL (see Figure 14).

Figure 14. Submitting the GET request
Submitting the GET request

If you look at the actual data, you will see that it's all there, but in a "flat" form; there is no mechanism for duplicating the hierarchy of the original XML (see Listing 15).

Listing 15. The URL request
http://localhost/XForms.php?name=Wolfgang+Amadeus+Mozart;genre=C;
accessibility=9;difficulty=9;totalscore=18;example=A+little+night
+music;example=Twinkle%2C+twinkle%2C+little+star;example=Don+Giovanni

Note that each name-value pair is separated with a semicolon (;). You can change that delimiter to an ampersand (&) using the separator attribute.


Conclusion

By this point, you should be able to create both simple and relatively complex XForms forms. These forms rely on the structure of an XML "instance" for both receiving and storing data, but they can also be made to emulate many of the more familiar capabilities of HTML forms. They provide enhanced interactivity, as well as a separation of data and presentation that makes it possible to use the same form on multiple devices. From here you should be able to understand what is necessary to build on these capabilities to create even more useful forms.


Download

DescriptionNameSize
Sample codexformsbasicsfiles.zip3KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into XML on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML
ArticleID=166699
ArticleTitle=XForms basics
publish-date=10102006