XForms tutorial - Chapter 2 - Collecting information from the user

Previous chapter | Next chapter

In the previous section, we have defined the data we would like to gather from the visitor. This section will focus on the interaction with the user, using XForms controls. This is the "View" part in the MVC approach.

Now we will start building the form by offering the user a first choice: Are you a citizen or do you represent a company? The code at the bottom of the page is the end product for this session. You can cut and paste this code into your favorite XForms editor/processor and inspect what it does. You may also preview the form here.

The document so far is our first working XForms form. Let us take a closer look at the code.

The first snippet of code defines a XForms group element, that for now contains a group label and an single select control select1. All input-related texts are drawn from the resources instance in the Model using standard XPath queries. The user-selected value of the control will be placed in the citizen_company element of the model instance (the ref attribute for the select1 control). When rendering the XForms document (for instance using the Smartsite XForms Workbench)  we will see the result of the select1: a single select option.

Working with resources

You can see how the textual information is read from the resources instance of the Model. Of course, instead of:

<xf:label ref="instance('resources')/texts/citizen_company/alert" />

we could have written:

<xf:label>Are you an individual citizen or representing a company?</xf:label>

As mentioned before, for reasons of maintainability we have decided to store all textual information in a single resources instance in the Model. Although this may seem an unnecessary indirection at first, it will prove its advantage at a later time.

The Select1 control

A select1 control does exactly what its name promises: it offers an opportunity to select one choice from a selection of options. A select1 control can be presented to the user in various ways. A dropdown list would offer a single selection, but a collection of radio buttons does the same. The translation from the XForms select1 control to an HTML representation is performed (server-side) by the XForms engine used in the application.

The Appearance attribute

To indicate the preference of the person designing the form, we can provide the engine with an appearance attribute (with possible values: minimal, compact and full) to the control. The engine will then decide how to represent the control. The Smartsite XForms Engine uses a lookup template, which can be customized to meet your specific needs.  In this case, compact is translated into a dropdown select whereas the full appearance is displayed as radio buttons.

The form

Above we see the form rendered (do not pay attention to styling for now; the engine has served us some standard styling that we will modify later on in the process). You can see the label, hint and help texts in action. On validation, something we will add later, the alert text might become visible.

Next we will create a new XForms group and then add the inputs for the citizen information. To keep the amount of sample code limited, we will limit the length of help, hint or alert texts unless they illustrate a particular point. It is, however, a good practice to always include these elements and to pay sufficient attention to the wording of these texts in order to maximize the conversion rate of your form. We insert this block of code, related to the first name of the citizen, into the group.

And repeat this for the other fields, until we have inputs for all required information. As you can see, the references to the texts are quite verbose. The total structure of the group will look like this.

Please note again that at this time we will not spend any time on styling of the form at this time; first we want to have a functional form and then we will spend some effort styling it appropriately.

After we have added all fields for the individual applicant, we now create a new XForms group and for now add a single field for a corporate applicant.

The form now looks like this:

More controls on the form

As you can see in the code so far, we have the three groups of controls: the selection for citizen or company, a group of inputs for citizens and a group with a single input for companies. It is good practice to test your forms in each of the major browsers, both functionally as well as esthetically.

Inspecting the resulting HTML

Just to satisfy our curiosity, we could inspect the resulting HTML source code. If you have the developer tools installed, you could do this by pressing F12 in Internet Explorer, or simply use the Source tab if you are using the Smartsite XForms Workbench.

Viewing source code 

You will see that the Smartsite XForms Engine has added a number of (jQuery) includes in the head section.

As can also be seen, the Smartsite XForms Engine amongst other things has created a <form> element in the body of the HTML, inside it defined three <fieldset> blocks (one for each of the <xf:group> elements), created a <div> and <span> structure for the inputs and help texts and alerts, generated unique ids for each element and added some classes to the elements for styling purposes. 

Previous chapter | Next chapter

Citizen or company

<!-- reference the default instance -->
<xf:group ref="." appearance="full">
    <xf:label>Events Application Form</xf:label>
    <!-- reference the value in the instance -->
    <xf:select1 ref="citizen_company" appearance="compact" >
	<xf:label ref="instance('resources')/texts/citizen_company/label"/>
	<xf:alert ref="instance('resources')/texts/citizen_company/alert"/>
	<xf:help  ref="instance('resources')/texts/citizen_company/help"/>
	<xf:hint  ref="instance('resources')/texts/citizen_company/hint"/>		
	<xf:itemset nodeset="instance('resources')/options/citizen_company/*">
	    <xf:label ref="." />
	    <xf:value ref="@value" />
	</xf:itemset>
    </xf:select1>
</xf:group>

Control for First Name field

<xf:input ref="citizen_firstname" incremental="true">
	<xf:label ref="instance('resources')/texts/citizen_firstname/label"/>
	<xf:hint  ref="instance('resources')/texts/citizen_firstname/hint" />
	<xf:alert ref="instance('resources')/texts/citizen_firstname/alert"/>
	<xf:help  ref="instance('resources')/texts/citizen_firstname/help" />
</xf:input>

Group structure

<xf:group ref="." >				
	<xf:input ref="citizen/citizen_firstname" incremental="true">
		<xf:label ref="instance('resources')/texts/step/citizen_firstname/label"/>
		<xf:hint  ref="instance('resources')/texts/step/citizen_firstname/hint" />
		<xf:alert ref="instance('resources')/texts/step/citizen_firstname/alert"/>
		<xf:help  ref="instance('resources')/texts/step/citizen_firstname/help" />
	</xf:input>
	<xf:input ref="citizen_middlename" incremental="true">
		<xf:label ref="instance('resources')/texts/step/citizen_middlename/label"/>
		<xf:hint  ref="instance('resources')/texts/step/citizen_middlename/hint" />
		<xf:alert ref="instance('resources')/texts/step/citizen_middlename/alert"/>
		<xf:help  ref="instance('resources')/texts/step/citizen_middlename/help" />
	</xf:input>
                      More controls …
</xf:group>

Question for corporate account

<xf:group>					
	<xf:input ref="company_name" incremental="true">
		<xf:label ref="instance('resources')/texts/step/company_name/label"/>
		<xf:hint  ref="instance('resources')/texts/step/company_name/hint" />
		<xf:alert ref="instance('resources')/texts/step/company_name/alert"/>
		<xf:help  ref="instance('resources')/texts/step/company_name/help" />
	</xf:input>
</xf:group>

The code so far

<?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:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:ev="http://www.w3.org/2001/xml-events">
	<head>
		<title>Events Application Form</title>
		<xf:model>
			<xf:instance xmlns="">
				<applicationdata>
					<!-- information re individual applicant -->
					<citizen_company required="true" />
					<citizen_firstname required="true" />
					<citizen_middlename/>
					<citizen_lastname required="true"/>	
					<citizen_street required="true"/>
					<citizen_number required="true"/>
					<citizen_postalcode required="true"/>
					<citizen_city required="true"/>
					<citizen_phone />
					<citizen_email required="true"/>
					<!-- information re company applicant -->
					<company_name required="true"/>
				</applicationdata>
			</xf:instance>
			<xf:instance id="resources"  xmlns="">
				<resources>			
					<texts>
						<!-- Step 0 -->
						<citizen_company>
							<label>Are you an individual citizen or representing a company?</label>
							<hint>Please make a selection.</hint>
							<alert>This selection is required.</alert>
							<help>Indicate if you apply as a citizen or on behalf of a company.</help>
						</citizen_company>
						<citizen_firstname>
							<label>Your first name</label>
							<hint>Please enter your first name.</hint>
							<alert>This information is required.</alert>
							<help>Your first name could be 'John'</help>
						</citizen_firstname>
						<citizen_middlename>
							<label>Your middle name</label>
							<hint>Please enter your middle name.</hint>
							<alert></alert>
							<help>Not everybody has a middle name.</help>
						</citizen_middlename>
						<citizen_lastname>
							<label>You last name</label>
							<hint>Please enter your last name.</hint>
							<alert>This information is required.</alert>
							<help>Your last name could be 'Smith'</help>
						</citizen_lastname>
						<citizen_street>
							<label>Your street name</label>
							<hint>Please enter the street name.</hint>
							<alert>This information is required.</alert>
							<help>The street name could be 'Broad Street'</help>
						</citizen_street>
						<citizen_number>
							<label>Your building number</label>
							<hint>Please enter your building number.</hint>
							<alert>This information is required.</alert>
							<help>The building number could be '27'</help>
						</citizen_number>
						<citizen_postalcode>
							<label>Postal code</label>
							<hint>Please enter the postal code.</hint>
							<alert>This information is required.</alert>
							<help>The postal code could be '1234 AB'</help>
						</citizen_postalcode>
						<citizen_city>
							<label>Your city name</label>
							<hint>Please enter your city name.</hint>
							<alert>This information is required.</alert>
							<help>The city name could be 'London'</help>
						</citizen_city>
						<citizen_phone>
							<label>Your phone number</label>
							<hint>Please enter your phone number.</hint>
							<alert></alert>
							<help>The phone number could be '+31152513700'</help>
						</citizen_phone>
						<citizen_email>
							<label>Your email address</label>
							<hint>Please enter your email address.</hint>
							<alert>This information is required.</alert>
							<help>You email address could be 'john@mydomain.com'</help>
						</citizen_email>
						<company_name>
							<label>Your company name</label>
							<hint>Please enter your company's name.</hint>
							<alert>This information is required.</alert>
							<help>Your company's name could be 'Acme'</help>
						</company_name>
					</texts>
					<options>
						<citizen_company>
							<option value="">Please select...</option> 
							<option value="citizen">I am a citizen</option>
							<option value="company">I represent a company</option>
						</citizen_company>
					</options>
				</resources>
			</xf:instance>
		</xf:model>
		<resources>
		</resources>
	</head>
	<body>
		<!-- reference the default instance -->
		<xf:group ref="." appearance="full">
			<xf:label>Events Application Form</xf:label>
			<!-- reference the value in the instance -->
			<xf:select1 ref="citizen_company" appearance="compact" >
				<xf:label       ref="instance('resources')/texts/citizen_company/label"></xf:label>
				<xf:alert       ref="instance('resources')/texts/citizen_company/alert"></xf:alert>
				<xf:help        ref="instance('resources')/texts/citizen_company/help"></xf:help>
				<xf:hint        ref="instance('resources')/texts/citizen_company/hint"></xf:hint>
				<xf:itemset nodeset="instance('resources')/options/citizen_company/*">
					<xf:label ref="." />
					<xf:value ref="@value" />
				</xf:itemset>
			</xf:select1>
		</xf:group>
		<xf:group ref=".">
			<xf:input ref="citizen_firstname" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_firstname/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_firstname/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_firstname/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_firstname/help"/>
			</xf:input>
			<xf:input ref="citizen_middlename" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_middlename/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_middlename/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_middlename/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_middlename/help"/>
			</xf:input>
			<xf:input ref="citizen_lastname" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_lastname/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_lastname/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_lastname/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_lastname/help"/>
			</xf:input>
			<xf:input ref="citizen_street" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_street/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_street/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_street/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_street/help"/>
			</xf:input>
			<xf:input ref="citizen_number" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_number/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_number/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_number/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_number/help"/>
			</xf:input>
			<xf:input ref="citizen_postalcode" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_postalcode/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_postalcode/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_postalcode/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_postalcode/help"/>
			</xf:input>	
			<xf:input ref="citizen_city" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_city/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_city/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_city/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_city/help"/>
			</xf:input>
			<xf:input ref="citizen_phone" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_phone/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_phone/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_phone/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_phone/help"/>
			</xf:input>
			<xf:input ref="citizen_email" incremental="true">
				<xf:label ref="instance('resources')/texts/citizen_email/label"/>
				<xf:hint  ref="instance('resources')/texts/citizen_email/hint" />
				<xf:alert ref="instance('resources')/texts/citizen_email/alert"/>
				<xf:help  ref="instance('resources')/texts/citizen_email/help"/>
			</xf:input>
		</xf:group>	
		<xf:group>
			<xf:input ref="company_name" incremental="true">
				<xf:label ref="instance('resources')/texts/company_name/label"/>
				<xf:hint  ref="instance('resources')/texts/company_name/hint" />
				<xf:alert ref="instance('resources')/texts/company_name/alert"/>
				<xf:help  ref="instance('resources')/texts/company_name/help"/>
			</xf:input>
		</xf:group>
	</body>
</html>