Some XForms basics
While not being a XForms tutorial we nevertheless should clarify some basic XForms concepts and terms to avoid confusion and help understanding the further explanations.
Concrete model and abstract UI
One often underemphasized aspect of XForms is that it’s ‘concrete about the model and abstract for the UI’:
You may define a fine-grained model of your data along with validations, calculations and types (usually XML Schema SimpleTypes). You may even use your own XSD- types or custom XPath functions and control every detail of data consistency as well as loading and saving of data via submissions.
For the UI it’s different: the XForms UI is abstract. XForms emphazises device- independence by using tag names for controls that avoid any association with visual interfaces such as ‘checkbox’ or ‘border’. XForms are designed for a specific purpose and not for a specific client or device. This allows the same form to be used with a browser, a mobile phone or even a voice application by transcoding the logical XForms UI elements to their appropriate equivalents in the target language (device language). When authoring XForms you should keep this in mind if you’re interested in supporting multiple clients.
Nevertheless most users will deal with XHTML as host documents in the overwhelming majority of cases. So what’s the advantage of being abstract?
First it reminds you that the rendering and concrete appearance of the control may vary from client to client but will always fulfill the same logical purpose. On the other hand it allows to automatically choose the most appropriate representation for a given case and shows the same instance nodes with different controls. Through useragent detection an implementation can choose the most appropriate profile for serving that specific client and show optimized controls and structures for it.
The language of specifications sometimes becomes a bit arcane and hard to understand for the average developer or page author. The good news is that you don’t need to read the full specification to start using XForms. There are many good tutorials out there that are much easier to consume. Nevertheless it’s good to understand some basics upfront:
XForms is NOT a standalone markup language!
Instead XForms is an embedded language meant to be used inside other XML markup languages. Of course the most prominent one is XHTML but there’s nothing preventing you from embedding it into VoiceML, SVG or any other XML markup language.
The language you’re are using to embed your XForms markup is called ‘host language’ and a concrete document (e.g. a XHTML page) is called a ‘host document’. XForms itself makes no assumptions about the host language besides being a well-formed XML language but relies on it e.g. for laying out pages. In the context of this document we’ll concentrate on embedding XForms in XHTML.
A XForms skeleton
To embed XForms into XHTML you have to watch a few things:
- put the XForms namespace on the root element of your document. If you’re unfamiliar with namespaces – don’t worry. Once you have accepted they need to be there you can quickly forget about them again. If not sure what to put there just copy ‘n paste from one of the sample forms. The snippet below defines namespaces for XHTML, XForms and further the namespace of XML events is needed as soon as you’re defining event-handlers in your document.
<?xml version="1.0" encoding="ISO-8859-1"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" ...
- add a <xforms:model> tag to the head or body section of your XHTML document (or ‘xf’ if you have choosen that for your prefix). Placing the <xforms:model> tag within the head is a mere convention that has been evolved over time. It is totally up to you where you put the model element.
The model itself might have one or more of the following children:
- instance – element wrapping or referencing the XML data of the form
- bind – to add constraints, states and datatypes to nodes
- submission – defines loading, processing and saving operations (interaction with some data source)
- action – listen on events during model-initialization
- add some XForms UI to the body of your document In this example a
<?xml version="1.0" encoding="ISO-8859-1"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xforms="http://www.w3.org/2002/xforms"> <head> <title>hello</title> <xforms:model id="hello-model"> (...) </xforms:model> </head> <body> <xforms:group> (...) </xforms:group> </body> </html>
- bind some of your controls to the model data
<?xml version="1.0" encoding="ISO-8859-1"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"> <head> <title>hello</title> <xf:model id="hello-model"> <xf:instance> <foo xmlns=““>bar</foo> </xf:instance> </xf:model> </head> <body> <xf:group> <xf:input ref=“/foo“> <xf:label>Foo</xf:label> </xf:input> </xf:group> </body> </html>
- You may now add bind elements to the model to constrain data in your instance(s) and UI controls to the group in the body of the document.
Anatomy of a XForms control
In XForms the structure of a control is constituted by a label and an ‘interaction’ widget:
<xforms:input ref=“foo“> <xforms:label>bar</xforms:label> </xforms:input>
The label element above is mandatory for each XForms control except output though most processors do not complain if you leave it out. The reasoning behind is that the Working Group wanted to make sure that the accessibility of a form is always given.
The ‘Value’ part of the control is the actual widget – that area that allows the user to give some input or interact with the system.
It is important to keep this structure in mind when you like to customize the rendering of controls via the automatically assigned CSS classes (see below).
At runtime you’ll see that the control wears a lot of information represented as CSS classes (Tip: you can use the Firebug extension for Firefox to take a look at the CSS classes). For the example above you’ll get the following for the input:
Each XForms control will have a xfControl class assigned. The type of control is given through the second class (here xfInput). The following classes are reflecting the current state of the Model Item Properties (MIP) for the instance node bound to the control. In this case the bound node of the input is readwrite, optional, enabled (relevant) and valid. There may be further classes for the XSD datatype, the incremental attribute etc.