blob: ea80e42d1f905150126d29e904d7c226d8533941 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../dtd/document-v10.dtd">
<document>
<header>
<title>XMLForm Wizard&#39;s How-To Step 1</title>
<authors>
<person name="Heidi-Marie Brannan"
email="heidi@wkwyw.net" />
</authors>
</header>
<body>
<s1 title="Step 1: XMLForm markup language">
<fixme author="DS">It may help to use screen shots here. It gets a bit
confusing, otherwise. What do you think?</fixme>
<fixme author="HB">Will do so when I can find the time.</fixme>
<p>First, we need to create our own form pages in XML.</p>
<ul>
<li>Create a folder called &#34;howto&#34; in
src\webapp\sample\xmlform.</li>
<li>Create and copy the following xml files, as instructed below, and
save them in the folder you created.</li>
</ul>
<s2 title="start.xml">
<p>Here is the first page. Copy and save as start.xml in the folder
src\webapp\mount\xmlform\howto.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document>
<br/><br/><br/>
<table align="center" width="50%" cellspacing="20">
<tr>
<td align="center">
<h1>
Welcome to the XMLForm How-To!
</h1>
</td>
</tr>
<tr>
<td align="center" class="info">
<code>
The following form allows users to join mailing lists.
They are given a choice of areas of interest.
Depending on their interests they will see a
selection of mailing lists to which they can sign up.
</code>
</td>
</tr>
<tr>
<td align="center">
<h3>
<a href="howto-wizard.html?cocoon-action-start=true">
Start!
</a>
</h3>
</td>
</tr>
</table>
</document>
]]>
</source>
<p>Note the value below of href:</p>
<source>
<![CDATA[
<a href="howto-wizard.html?cocoon-action-start=true">
]]>
</source>
<p>The text between &#34;cocoon-action-&#34; and &#34;=true&#34; is
passed to the method prepare of HowtoWizardAction.java (to be written
in step 4). In the above case, the value to be passed is
&#34;start&#34;. This command, &#34;start&#34;, will reset the state of
the form by removing any remaining form values.</p>
</s2>
<p>The remaining XML pages are listed below in order:</p>
<ul>
<li>registration.xml</li>
<li>interest.xml</li>
<li>organicGardening.xml</li>
<li>cooking.xml</li>
<li>smallholding.xml</li>
<li>confirm.xml</li>
<li>end.xml</li>
</ul>
<s2 title="registration.xml">
<p>registration.xml lets the user register a username, password and
email address in order to join the mailing lists (chosen next).</p>
<p>XMLForms has the ability to choose the scope of form persistence
to be either per-session or per-request. This is selected in the
xmlform-scope parameter when the action is set up in the sitemap.
In forms that span multiple screens, you will always want to use
per-session. Additionally, multiple forms can be active at once.
The xf:form&#39;s id attribute is the discriminator that allows this
functionality. </p>
<p> It is mentioned early because this discriminator is also required
in the form source themselves. Our session identifier (as seen in
registration.xml below in the xf:form element), form-feedback, is
matched by the sitemap&#39;s map:parameter name-value pair shown here:</p>
<source>
&#60;map:parameter name=&#34;xmlform-id&#34; value=&#34;form-feedback&#34;/&#62;
</source>
<p>The view attribute of the xf:form element should contain the name of
the current xml file. As it is used by the form action
to determine which page was submitted, mapping the data on the form to
current logic in the action. The name of the view should simply be
unique within the form, but it is most convenient to name the view after
the base of the filename. So in this case, we will name our view
&#34;registration&#34;. In step 4 static string constants are used to unify
the naming and allow for easier maintenance </p>
<p>The action attribute should contain the URL you are using in
the sitemap. When implementing, it is easier to put all your pages for a
given form in a single folder but have the relative URL the same between
the different folders. This allows a single sitemap template to be used for
each of your different forms if desired. The URL is encoded directly to the
HTML action that is generated, so if this parameter is incorrect you will see
a &#34;Resource Not Found&#34; error from Cocoon 2.</p>
<p>The caption element is the page heading. Following that, we have error
elements which are used if you have validation set in your sitemap.
When an error is found, the error text will be displayed once the user
clicks the next button on your form.</p>
<p>Next we see the input options for the user, such as xf:textbox,
which will display a textbox. Each of these options has a very
important ref attribute whose value is mapped to the JavaBean.
If you are validating this input then it must have a violations
element inside it. The violations element serves as a container
or place holder for validation errors. It has a single optional
attribute &#34;class&#34; which refers to the CSS class to use when
displaying validation errors.</p>
<p>The format of the ref item is XPath, and the mapping is through
<link href="http://jakarta.apache.org/commons/jxpath/">JXPath</link>.
JXPath is very flexible, it is beyond the scope of this document to
describe it in detail.</p>
<p>Finally, the form needs a submit element This enables the user to
continue on through the rest of the form.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document xmlns:xf="http://apache.org/cocoon/xmlform/1.0">
<xf:form id="form-feedback" view="registration" action="howto-wizard.html">
<xf:caption>Registration</xf:caption>
<error>
<xf:violations class="error"/>
</error>
<xf:textbox ref="/userName">
<xf:caption>Last Name</xf:caption>
<xf:violations class="error"/>
</xf:textbox>
<xf:textbox ref="/email">
<xf:caption>Email</xf:caption>
<xf:help>Please check this carefully</xf:help>
<xf:violations class="error"/>
</xf:textbox>
<xf:password ref="/password">
<xf:caption>Password</xf:caption>
<xf:violations class="error"/>
</xf:password>
<xf:submit id="next" class="button">
<xf:caption>Next</xf:caption>
<xf:hint>Go to next page</xf:hint>
</xf:submit>
</xf:form>
</document>
]]>
</source>
</s2>
<s2 title="interest.xml">
<p>This XML page lets the user select areas of interest. Based on
their selections a user will later view a group of mailing
lists on subsequent pages. The logic that determines which pages are
shown next is found in the file, HowtoWizardAction.java which will
be explained later in step 4.</p>
<p>This page consists mainly of check boxes which are either true or false.</p>
<source>
<![CDATA[
<xf:selectBoolean ref="/organicGardening">
<xf:caption>Organic Gardening</xf:caption>
</xf:selectBoolean>
]]>
</source>
<p>The page asks the user what their areas of interest are. There are 3
check boxes with the following captions of organic gardening, cooking
and Smallholding management. At the bottom of the page is a previous and
next button.
</p>
<p>Below is the page which you can copy into the folder
&#34;howto&#34;.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document xmlns:xf="http://apache.org/cocoon/xmlform/1.0">
<xf:form id="form-feedback" view="interest" action="howto-wizard.html">
<xf:caption>Areas of Interest</xf:caption>
<xf:selectBoolean ref="/organicGardening">
<xf:caption>Organic Gardening</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/cooking">
<xf:caption>Cooking</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/smallholdingManagement">
<xf:caption>Smallholding Management</xf:caption>
</xf:selectBoolean>
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
<xf:hint>Go to previous page</xf:hint>
</xf:submit>
<xf:submit id="next" class="button">
<xf:caption>Next</xf:caption>
<xf:hint>Go to next page</xf:hint>
</xf:submit>
</xf:form>
</document>
]]>
</source>
</s2>
<s2 title="organicGardening.xml">
<p>If the user ticked the organic gardening box on the previous page,
interest.xml, organicGardening.xml will be the next page to display. This
page shows a selection of mailing lists from which the user can chose.
It is very similar to the previous page which contained three tick
boxes. The user has the choice of moving forward through the form or
back to the previous page to adjust their areas of interest. This is decided
in the perform method of HowtoWizardAction.java.</p>
<p>In a MVC pattern, it's clear to see that the form action is the controller,
dealing only with the logic behind the presentation. The pages that we are
discussing here are the views, and the model is the bean that is describe
in step 3.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document xmlns:xf="http://apache.org/cocoon/xmlform/1.0">
<xf:form id="form-feedback" view="organicGardening" action="howto-wizard.html">
<xf:caption>Organic Gardening Mailing Lists:</xf:caption>
<xf:selectBoolean ref="/flowers">
<xf:caption>Flowers</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/vegetables">
<xf:caption>Vegetables</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/fruitTrees">
<xf:caption>Fruit Trees</xf:caption>
</xf:selectBoolean>
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
<xf:hint>Go to previous page</xf:hint>
</xf:submit>
<xf:submit id="next" class="button">
<xf:caption>Next</xf:caption>
<xf:hint>Go to next page</xf:hint>
</xf:submit>
</xf:form>
</document>
]]>
</source>
</s2>
<s2 title="cooking.xml">
<p>The next page is a selection of cookery mailing lists, very similar
to the organicGardening.xml page. This page will appear if the user
ticked the organic gardening option on the interest.xml page. Again
the perform method checks the beans value and depending on these decides
whether or not to show this page. Conceptually the pages displayed are
sequenced by the controller and the logic therein.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document xmlns:xf="http://apache.org/cocoon/xmlform/1.0">
<xf:form id="form-feedback" view="cooking" action="howto-wizard.html">
<xf:caption>Cooking Mailing Lists:</xf:caption>
<xf:selectBoolean ref="/traditionalRecipes">
<xf:caption>Traditional Recipes</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/soups">
<xf:caption>Soups</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/veganCookery">
<xf:caption>Vegan Cookery</xf:caption>
</xf:selectBoolean>
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
<xf:hint>Go to previous page</xf:hint>
</xf:submit>
<xf:submit id="next" class="button">
<xf:caption>Next</xf:caption>
<xf:hint>Go to next page</xf:hint>
</xf:submit>
</xf:form>
</document>
]]>
</source>
</s2>
<s2 title="smallholdingManagement.xml">
<p>Again, this page is similar to organicGardening.xml, cooking.xml as
it gives the user a choice of mailing lists. This page will only
appear if the user selected Smallholding Management as an interest on
the interest.xml page.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document xmlns:xf="http://apache.org/cocoon/xmlform/1.0">
<xf:form id="form-feedback" view="smallholdingManagement" action="howto-wizard.html">
<xf:caption>Smallholding Management Mailing Lists</xf:caption>
<xf:selectBoolean ref="/pigKeeping">
<xf:caption>Pig Keeping</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/pygmyGoats">
<xf:caption>Pygmy Goats</xf:caption>
</xf:selectBoolean>
<xf:selectBoolean ref="/henKeeping">
<xf:caption>Hen Keeping</xf:caption>
</xf:selectBoolean>
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
<xf:hint>Go to previous page</xf:hint>
</xf:submit>
<xf:submit id="next" class="button">
<xf:caption>Next</xf:caption>
<xf:hint>Go to next page</xf:hint>
</xf:submit>
</xf:form>
</document>
]]>
</source>
</s2>
<s2 title="confirm.xml">
<p>This page shows the user all of the previously submitted data. A user
can change any of the information by clicking the previous button and
adjusting previous selections. Otherwise, the user can click the
finish button to go to the final page, end.xml.</p>
<p>While the pages were being filled out and submitted to the form
action, the fields were being individually validated against the schema
and the results applied to our bean using the JXPath expressions that were
entered in the ref attributes on each field of the page. By the time you
get to this point, the model bean will contain all the data that was
assigned to it, and you can start to use it.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document xmlns:xf="http://apache.org/cocoon/xmlform/1.0">
<xf:form id="form-feedback" view="confirm" action="howto-wizard.html">
<xf:caption>Confirm Input</xf:caption>
<!-- from page1 -->
<xf:output ref="/userName">
<xf:caption>User Name</xf:caption>
</xf:output>
<xf:output ref="/email">
<xf:caption>Email</xf:caption>
</xf:output>
<xf:output ref="/password">
<xf:caption>Password</xf:caption>
</xf:output>
<!-- from page2 -->
<xf:output ref="/organicGardening">
<xf:caption>Organic Gardening</xf:caption>
</xf:output>
<xf:output ref="/cooking">
<xf:caption>Cooking</xf:caption>
</xf:output>
<xf:output ref="/smallholdingManagement">
<xf:caption>Smallholding Management</xf:caption>
</xf:output>
<!-- from page3 -->
<xf:output ref="/flowers">
<xf:caption>Flowers</xf:caption>
</xf:output>
<xf:output ref="/vegetables">
<xf:caption>Vegetables</xf:caption>
</xf:output>
<xf:output ref="/fruitTrees">
<xf:caption>Fruit Trees</xf:caption>
</xf:output>
<!-- from page4 -->
<xf:output ref="/traditionalRecipes">
<xf:caption>Traditional Recipes</xf:caption>
</xf:output>
<xf:output ref="/soups">
<xf:caption>Soups</xf:caption>
</xf:output>
<xf:output ref="/veganCookery">
<xf:caption>Vegan Cooking</xf:caption>
</xf:output>
<!-- from page5 -->
<xf:output ref="/pigKeeping">
<xf:caption>Pig Keeping</xf:caption>
</xf:output>
<xf:output ref="/pygmyGoats">
<xf:caption>Pygmy Goats</xf:caption>
</xf:output>
<xf:output ref="/henKeeping">
<xf:caption>Hen Keeping</xf:caption>
</xf:output>
<!-- submit -->
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
<xf:hint>Go to previous page</xf:hint>
</xf:submit>
<xf:submit id="next" class="button">
<xf:caption>Finish</xf:caption>
<xf:hint>Submit the finished form</xf:hint>
</xf:submit>
</xf:form>
</document>
]]>
</source>
<p>The final confirmation page is generated by querying the model
bean and displaying it. This is accomplished using the xf:output
element which specifies what value to display with the ref attribute,
again in JXPath syntax.</p>
<p>It's interesting to note that because this is a bean, business
logic could be embedded in the bean. So if this were a shopping cart
bean, we could have read-only business methods such as getTotalCost(),
which would be the sum of the individual item costs plus calculated
costs such as shipping and tax. You would have no problem displaying
that information on the form since the xf:output simply needs a JXPath
expression to query those methods. In such an example, the perform
method could be used to transactionally add the cart to the order
queue.</p>
</s2>
<s2 title="end.xml">
<p>end.xml is the final page. It informs the user of successful form
completion and provides the user with the option to return to the
start page.</p>
<source>
<![CDATA[
<?xml version="1.0" ?>
<document>
<br/><br/><br/>
<table align="center" width="50%" cellspacing="20">
<tr>
<td align="center">
<h1>
You have reached the last page of the How-To Form example!
</h1>
</td>
</tr>
<tr>
<td align="center" class="info">
<code>
Your registration form was processed successfully.
</code>
</td>
</tr>
<tr>
<td align="center">
<h3>
<a href="howto-wizard.html">Go to home page.</a>
</h3>
</td>
</tr>
</table>
</document>
]]>
</source>
</s2>
<p><link href="howto-xmlform-wizard-2.html">Step 2: Validation</link></p>
</s1>
</body>
</document>