XForms is gaining momentum rapidly, with support available for common browsers using extensions or plugins, and through products like the IBM® Workplace Forms technology (see the Resources section at the end of this article to find out more). Its flexibility and power make it attractive to Web developers, and its small footprint and client-side processing, make it attractive to systems administrators. The W3C is currently reviewing XForms 1.1 as a Working Draft document (1.0 is an official Internet Recommendation, which puts it on par with things like XHTML, PNG, and CSS), and IBM is currently spearheading an effort to merge competing XML-based forms standards with the features and abilities of XForms.
This article shows you how to use actions and events with XForms, and how to control the format of the form's output. Part 1 covered various browsers and their plugins that are necessary for viewing and interacting with XForms documents, so that won't be covered again here. Part 2 showed you how to create an XForms-based form using any of the available controls, how to create a data model, and the different types of basic submission actions that are available. If you are following along, or you already have a plugin working with your favorite browser, you can jump in and download the code for this article and view the example XForms.
XForms uses the XML Events standard to attach event handlers to specific elements in a document. XML Events is an XML representation of the DOM event model from HTML. Let's take a quick look at the event model, in case you haven't encountered it before.
When an event occurs (a click or a mouse-over, for example) the capture phase begins. Starting at the root of the document tree and moving down to the element where the event was triggered, each element is given the opportunity to handle the event. If the event reaches the target element without being handled and the event type allows it, the bubbling phase begins. The event travels back up the tree towards the document root.
Elements can be observers; the observer's event handler will be activated as the event passes through in both directions. An event handler can only listen to one phase, so you need to attach two handlers to an element if you want to do something during each phase.
Listing 1 shows you a fairly simple XHTML document. When this is loaded into your Web browser, a DOM tree, like the one in Figure 1 is created to represent this document.
Listing 1. A simple XHTML document
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Event path</title> </head> <body> <h1>Event path</h1> <p> What happens if you click on <em>this</em> element? </p> </body> </html>
If a user clicks on the emphasized "this" in the
<p> element, an event will begin to travel along the red path in Figure 1; this represents the capture phase. If no event handlers processed the click, the event will travel back up the same path until it comes back to the root element, where the default click handler will ignore it.
Figure 1. An event traveling down the DOM tree
mouseover, to process the event. For example, if you change the
Listing 2. An XHTML event handler
<p> What happens if you click on <em onclick="alert('Click!'); return true;">this</em> element? </p>
This technique has been working for years; why isn't it good enough for XForms to use? The event name is hard-coded into the language (XHTML in this case); to add a new event, you need to add a new attribute. The event name is also very hardware-specific, such as "onclick" when an element is activated (it could be clicked with a mouse, given focus and activated by pressing Return on a keyboard, or triggered in any other way you can imagine). You can only use one scripting language to create a handler, since you can't have more than one instance of an attribute in the observer. And, finally, the event handling scripts are intertwined with the form's presentation markup.
XForms solves these problems by applying XML and leveraging the XML Events standard (see Resources). The event, observer, and handler are specified as part of an XForms control. For example, the XHTML in Listing 3 will pop up an alert when clicked.
Listing 3. XHTML event and handler embedded in a
<button name="Click me" onclick="alert("You clicked me!"); return true;"/>
Listing 4 shows you how to accomplish the same thing using XForms.
Listing 4. XForms event and handler
<xf:trigger> <xf:label>Click me</xf:label> <xf:message level="modal" ev:event="DOMActivate">You clicked me!</xf:message> </xf:trigger>
This creates an observer, watching for the
DOMActivate event (the same as the
onclick event in XHTML) to the
<xf:message> action (which displays an alert message) to the trigger's. When you click the trigger, it pops up an alert.
The XForms standard lists a large number of events, which can be aimed at a control (any of the
<xf:upload> elements), the model,
<xf:submission>, and the instance. Check the Resources section for sources of information about the various events and how to use them.
As you saw in Listing 4, an XForms event handler (such as
<xf:message>) is attached to the specified event. There are a number of XForms actions that can be used in an event handler:
<xf:action>-- A container for other actions, which will be invoked in the order specified inside the
<xf:dispatch>-- Dispatch an event (either one you've made up, or one of the predefined XForms events) to a given target element. You can specify whether or not the event bubbles up towards the root if the target element doesn't handle it.
<xf:load>-- Load the specified URL, either in a new window, or replacing the current document.
<xf:message>-- Display a specified message (which can be in the instance, loaded from an external file, or encapsulated in the
<xf:message>element) to the user.
<xf:rebuild>-- Cause the XForms processor to rebuild any internal data structures used to track dependencies between instance data elements. Causes an
<xf:recalculate>- Recalculate and update instance data elements. Causes an
<xf:refresh>-- Refresh the XForms user interface, updating the controls to reflect the current state of the instance. Causes an
<xf:reset>-- Reset the form by dispatching an
xforms-resetevent. You probably don't ever need to use this, since users never reset forms to their original state.
<xf:revalidate>-- Revalidate the instance data as specified by the processing model. Causes an
<xf:send>-- Dispatches an
xforms-submitevent, activating the form's submission processing.
<xf:setfocus>-- Dispatch an
xforms-focusevent to the specified control. This can be used to implement accessibility features, etc.
<xf:setvalue>-- Explicitly set the value of the specified data instance element.
Let's take the simple search form created in the first two parts of this series. As you'll recall, it has a single text entry field for search keywords, and one button for submitting the search. In Listing 5, some
DOMFocusIn event handlers (which have been highlighted) are added to add "ephermeral" pop-ups to the controls.
Listing 5. Adding helpful messages with
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events"> <head> <title>Search Form</title> <xf:model> <xf:instance> <data xmlns=""> <query/> </data> </xf:instance> <xf:submission action="http://localhost/imaginary-search-engine" method="get" id="submit-search"/> </xf:model> </head> <body> <h1>Search Form</h1> <p> Enter a search string, then click the Search button. </p> <p> <xf:input ref="query"> <xf:label>Find:</xf:label> <xf:message level="ephemeral" ev:event="DOMFocusIn"> Enter your search keywords here, then click Search. </xf:message> </xf:input> <xf:submit submission="submit-search"> <xf:label>Search</xf:label> <xf:message level="ephemeral" ev:event="DOMFocusIn"> Click here to begin searching for your keywords. </xf:message> </xf:submit> </p> </body> </html>
These are often rendered as tool tips or similar mini-windows, as shown in Figure 2.
Figure 2. The
Now that you have a good foundation for handling events with XForms, take a look next at some more advanced submission topics and options.
Part 2 of this series took a quick look at the various basic XForms submission methods, which are recapped here:
<xf:submission method="form-data-post" action="url"/> is the same as
<form method="post" enctype="multipart/form-data"> in HTML, and can be handled at the receiving URL in the same way. The data instance is serialized as multipart form data.
<xf:submission method="get" action="url"/> is the same as
<form method="get"> in HTML. The data instance is serialized with URL encoding and appended to the specified URL.
<xf:submission method="post" action="url"> sends the form's current data model instance to the specified URL as an XML document. There is no equivalent in HTML.
<xf:submission method="put" action="url"> writes the form's current data model instance to the specified URL as an XML file, assuming you have
PUT permissions for that URL on the server. There is no equivalent in HTML.
<xf:submission method="urlencoded-post" action="url"> is the same as
<form method="post" enctype="application/x-www-form-urlencoded"> in HTML. The data instance is serialized as multipart related data.
get methods support file: and http:/https: URLs, while the others support http:/https: and mailto: URLs.
<xf:submission> element allows several optional attributes to help control the XML created out of the data model instance by the XForms processor:
version-- Specify the version of XML to create (default is "1.0" obviously)
indent-- Specify whether the generated XML should include whitespace to improve readability
mediatype-- Specify the MIME type for the generated XML (you should make sure the media type is compatible with application/xml, the default)
encoding- Specify a text encoding for the generated XML
omit-xml-declaration-- Specify whether to leave out the XML declaration
standalone- Specify whether to include a standalone declaration in the XML
cdata-section-elements- A comma-separated list of elements that should be serialized as CDATA sections
includenamespaceprefixes-- A comma-separated list of namespaces; elements matching these namespaces are included in the output XML
separator attribute can also be used to specify the character used to separate key=value pairs in URL-encoding (the default is ";").
Modifying the basic search form slightly to use a
put to a file so you can see its XML output gives the results in Listing 6, which shows you what the default XML created by XForms from the data model instance looks like. It includes the XML namespace declarations from the XForms document, which aren't necessarily appropriate for the instance.
Listing 6. Sample XForms XML output
<?xml version="1.0" encoding="UTF-8"?> <data xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events"> <query>xforms standard</query> </data>
includenamespaceprefixes="#default" to the
<xf:submission> element provides you with the document in Listing 7, which only includes the default namespaces that you've assigned to the model. In this case, there are no namespaces, and you get a basic, unadorned XML document containing only the data from the data model instance.
Listing 7. Default namespace only
<?xml version="1.0" encoding="UTF-8"?> <data xmlns=""> <query>another test</query> </data>
<xf:submission> and its options, you have great control over how your data is sent to the server.
With XForms, it's entirely possible to have a form without any sort of
<xf:submission> element. The data lives and dies with the user's Web browser, while still doing something useful. For example, you could pretend that you're a high school computer science student (see Figure 3), and build a temperature converter.
Figure 3. A high school computer science assignment: Make a temperature converter
This is a handy tool (see Listing 8) if you've got Internet friends who complain about how hot or cold their area is, and you want to quickly figure out what the problem is with their temperature.
Listing 8. Temperature converter, XForms style
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/ TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ev="http://www.w3.org/2001/xml-events"> <head> <title>Temperature Converter</title> <xf:model> <xf:instance> <data xmlns=""> <f/> <c>20</c> </data> </xf:instance> </xf:model> </head> <body> <h1>Temperature Converter</h1> <p> Enter a value, then click the appropriate button to convert between units: </p> <p> <xf:input ref="c"><xf:label>Degrees Celcius (°C): </xf:label></xf:input> </p> <p> <xf:input ref="f"><xf:label>Degrees Fahrenheit (°F): </xf:label></xf:input> </p> <p> <xf:trigger> <xf:label>°C → °F</xf:label> <xf:action ev:event="DOMActivate"> <xf:setvalue ref="f" value="number(/data/c) * 9 div 5 + 32"/> </xf:action> </xf:trigger> <xf:trigger> <xf:label>°F → °C</xf:label> <xf:action ev:event="DOMActivate"> <xf:setvalue ref="c" value="( number(/data/f) - 32 ) * 5 div 9"/> </xf:action> </xf:trigger> </p> </body> </html>
The XForms bits in Listing 8 have been highlighted. First you declare a really simple data model, one that knows about a single temperature in both the Celcius (Metric) and Fahrenheit (Imperial) scales. You only fill in one data value; after all, you want a computer to do this conversion for you instead of figuring it out.
You've also created two input fields that let the user enter a temperature value in either scale. Note that you haven't used the
<xf:bind> element to constrain the input data to numbers; that's one of the adavanced XForms topics not covered in this series.
Finally, make one button for converting Celcius to Fahrenheit, and one button for going the other way. Inside the
<xf:action> element, use
<xf:setvalue> to calculate the other temperature without using any sort of scripting (that's just an XPath expression in the
value attribute), and definitely without requiring any sort of server intervention.
This temperature converter is what XForms is all about, providing a richer client experience without taxing the Web server.
This article provided a quick overview of the various XForms actions and showed how you can create observers for XForms events inside of XForms controls. You also looked at the various kinds of submission techniques, and the options you can use to control how your data is sent to the server.
This series of articles has provided you with the basics to get up and running to create your own XForms forms. You can now begin crafting your own XForms experiments!
|Part 3 sample code||xforms3.zip||3KB||HTTP|
Visit the XForms home at W3C.
XForms.org: The Nexus for Intelligent Web Apps contains a treasure-trove of information and links on XForms.
Read Part 2 in this series, Introduction to XForms.
Read Part 1 in this series, Introduction to XForms.
Read about Web Forms 2.0, a similar but competing spec.
Get ready for XForms (devleoperWorks, Septebmer 2002) provides a useful overview of this important technology.
For an excellent introductory tutorial on XPath, see Get Started With XPath (developerWorks, May 2004).
For an article demonstrating the relative strengths of using XPath, read The Java XPath API (developerWorks, July 2006).
For an article that looks at some of the spcific features of XPath, read XML for Data: What's New in XPath 2.0? (developerWorks, September 2002).
For an overview of how XML Events came about, what it's useful for, and how it works, see Introduction to XML Events (developerWorks, November 2004).
Read John Boyer's blog on XForms, Web Forms 2.0 and the future of XML content on the Web.
SVG and XForms, a Primer (developerWorks, November 2003) provides an overview of the two technologies and highlights the potential synergies between them.
Read XForms Essentials by Micah Dubinko from O'Reilly Media.
For a good starting point for XForms research, read
Ten Favorite XForms Engines from XML.com.
For an interactive, cross-platform tutorial on W3C XForms, visit the XForms institute.
Get a historical perspective on the origins and purpose of XForms in this brief history of SGML.
To get a good grounding in XML, read the Introduction to XML tutorial (developerWorks, August 2002).
Learn all about XML at the developerWorks XML zone.
Get products and technologies
Get the XForms extension for Mozilla, Firefox, or Seamonkey.
Get the XForms plugin for Internet Explorer 6.
Get the Trial: Lotus Forms (formerly Workplace Forms product).
Get the XML Path Language (XPath)
Version 1.0 specification from the W3C.
Get the XML Events specification from the W3C.
Chris Herborth is an award-winning senior technical writer with more than 10 years of experience writing about operating systems and programming. When he's not playing with his son Alex or hanging out with his wife Lynette, Chris spends his spare time designing, writing, and researching (that is, playing) video games.