Multi-page form

This example uses a simple two-page form to enter data for a simulated email message.

Start the example here.

Although a two-page form does not make sense for three fields when run from a desktop browser, this demonstrates how the Flow makes it easy to keep track of the user's "position" in the application flow. Just imagine you're working on a tiny mobile device for a minute.

We won't use Cocoon Forms here, but simply bind a JavaScript object to our form manually.

Notice how little code is needed to keep state while the user can freely move between the pages without losing data.

The sitemap

There's nothing new in the sitemap, our use of variables allows the exact same sitemap to be reused for both our Flow examples.

The only specific thing is the importing of the multi-page.js Flowscript, but this was already present for the previous example:

<map:flow id="flow" language="javascript">
<map:script src="number-guess/guess-number.js"/>
<map:script src="multi-page/multi-page.js"/>
<map:script src="java-shapes/java-shapes.js"/>
</map:flow>

Flowscript code

Here's the Flowscript which drives the multi-page form example:

multi-page.js
0001 /*
0002 * Copyright 1999-2004 The Apache Software Foundation.
0003 *
0004 * Licensed under the Apache License, Version 2.0 (the "License");
0005 * you may not use this file except in compliance with the License.
0006 * You may obtain a copy of the License at
0007 *
0008 * http://www.apache.org/licenses/LICENSE-2.0
0009 *
0010 * Unless required by applicable law or agreed to in writing, software
0011 * distributed under the License is distributed on an "AS IS" BASIS,
0012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 * See the License for the specific language governing permissions and
0014 * limitations under the License.
0015 */

0017 // Multi-page Flow example
0018 // Simple multi-page form, without using Cocoon Forms

0020 var date = new Packages.java.util.Date();

0022 // simulated email message data
0023 function MessageData() {
0024 this.sender = "you@somewhere.com";
0025 this.subject = "Type the subject here";
0026 this.text = "Type the text of your message here";
0027 }

0029 // page flow
0030 function public_startMultiPage() {
0031 var message = new MessageData();

0033 while(true) {

0035 // decide which page to show based on request parameters
0036 var page = "page1";
0037 if(cocoon.request.getParameter("action_send") != null) {
0038 break;
0039 } else if(cocoon.request.getParameter("action_page2") != null) {
0040 page = "page2";
0041 }

0043 // show form and wait for results
0044 cocoon.sendPageAndWait("multi-page/views/" + page, { "message" : message, "date" : date });

0046 // now for the boring part: copy form data into message
0047 // that's where Forms bindings would help
0048 var tmp = cocoon.request.getParameter("sender");
0049 if(tmp != null) message.sender = tmp;

0051 tmp = cocoon.request.getParameter("subject");
0052 if(tmp != null) message.subject = tmp;

0054 tmp = cocoon.request.getParameter("text");
0055 if(tmp != null) message.text = tmp;
0056 }

0058 // user selected "send", show message contents
0059 cocoon.sendPage("multi-page/views/result", { "message" : message });
0060 }

It is not more complicated than the previous example, but slightly longer due to the (boring) copying of request parameters into the message object. This boring part is where Cocoon Forms will come into play, by making it easier to bind data to values edited in a form.

By copying values into the message object after each submission, we allow the user to freely move between pages without losing data.

JXTemplate view

Nothing special in the form view, this is very similar to the previous example.

We're only using two submit buttons, one to move between pages and one to actually submit the data and go to the result page.

<page id="page">
<title> Flow example: multi-page form </title>
<content>
<h2> Multi-page form: page 1 (${date}) </h2>
<form method="get" action="${continuation.id}.continue">
<table>
<tr>
<td> Sender </td>
<td>
<input type="text" size="40" name="sender" value="${message.sender}"/>
</td>
</tr>
<tr>
<td> Subject </td>
<td>
<input type="text" size="40" name="subject" value="${message.subject}"/>
</td>
</tr>
</table>
<input type="submit" name="action_page2" value="Page 2"/>
<input type="submit" name="action_send" value="Send message"/>
</form>
<p class="footer">
<a href="../docs/index.html"> Flow examples </a>
</p>
</content>
</page>

This is page 1. The page 2 is similar but shows the text field instead of the fields present on page 1.