Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 1801 invoked from network); 27 Sep 2007 20:00:16 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 27 Sep 2007 20:00:16 -0000 Received: (qmail 60560 invoked by uid 500); 27 Sep 2007 19:59:47 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 60499 invoked by uid 500); 27 Sep 2007 19:59:47 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 60487 invoked by uid 99); 27 Sep 2007 19:59:47 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Sep 2007 12:59:47 -0700 X-ASF-Spam-Status: No, hits=-98.5 required=10.0 tests=ALL_TRUSTED,WEIRD_PORT X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Sep 2007 19:59:44 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 66EA11A9852; Thu, 27 Sep 2007 12:58:52 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r580139 [8/28] - in /cocoon/site/site/2.2: ./ blocks/ blocks/ajax/ blocks/ajax/1.0/ blocks/ajax/1.0/apidocs/ blocks/ajax/1.0/css/ blocks/ajax/1.0/images/ blocks/ajax/1.0/images/logos/ blocks/css/ blocks/forms/ blocks/forms/1.0/ blocks/forms... Date: Thu, 27 Sep 2007 19:57:38 -0000 To: cvs@cocoon.apache.org From: reinhard@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070927195852.66EA11A9852@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: cocoon/site/site/2.2/blocks/forms/1.0/1351_1_1.html URL: http://svn.apache.org/viewvc/cocoon/site/site/2.2/blocks/forms/1.0/1351_1_1.html?rev=580139&view=auto ============================================================================== --- cocoon/site/site/2.2/blocks/forms/1.0/1351_1_1.html (added) +++ cocoon/site/site/2.2/blocks/forms/1.0/1351_1_1.html Thu Sep 27 12:56:05 2007 @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + Cocoon Forms + + + + + + + +
+

Apache » Cocoon »

+
+ + + +
+ + +

Migration guide

Introduction

Forms block has been recently adapted to use features that servlet services +framework provides. For in-depth details of adoption process take a look at +COCOON-1991 +issue.

Here you'll find description of migration process which should be easy and +straightforward. It is assumed that you already have proper block structure +created with archetype, see Your first Cocoon application +using Maven 2.

Connecting servlets

First of all, in order to get access to the resources that Forms block makes +available you need to create a connection to its servlet. Open +src/main/resources/META-INF/cocoon/spring/servlet-service.xml for edition and +put this configuration inside <servlet:context> tag:

<servlet:connections>
+  <entry key="ajax" value-ref="org.apache.cocoon.ajax.impl.servlet"/>
+  <entry key="forms" value-ref="org.apache.cocoon.forms.impl.servlet"/>
+</servlet:connections>
+

Correcting links and paths

You will need to perform massive find-and-replace operation multiple times. +Previously, all external (available to the browser) resources were loaded with +special _cocoon/** matcher and internal resources (like XSL files) were +loaded with resource:// scheme. Both are now considered as bad +practice.

+Special, global matcher cannot be easily provided in real blocks environment +because it does not support concepts like block's polymorphism and makes Cocoon +more monolithic. Loading resources of other block with resource: is +also discouraged because resources location within block is not part of +any block's contract. Only resources that are available with servlet: +scheme are part of block's contract and should not change without significant +reasoning.

Now you will see list of couple old and new paths/links. Performing normal +find-and-replace operation on your block that you are migrating should be +enough. Here is the list:

resource://org/apache/cocoon/forms/flow/javascript/Form.js
+servlet:forms:/resource/internal/flow/javascript/Form.js
+
+resource://org/apache/cocoon/forms/generation/jx-macros.xml
+servlet:forms:/resource/internal/generation/jx-macros.xml
+
+resource://org/apache/cocoon/forms/system/i18n
+servlet:forms:/resource/internal/i18n
+
+resource://org/apache/cocoon/forms/resources/forms-page-styling.xsl
+servlet:forms:/resource/internal/xsl/forms-page-styling.xsl
+
+resource://org/apache/cocoon/forms/resources/forms-advanced-field-styling.xsl
+servlet:forms:/resource/internal/xsl/forms-advanced-field-styling.xsl
+

forms-samples-styling.xsl

If you use forms-samples-styling.xsl for transforming your Forms into HTML +code you will have to update it to newer version. Important change (apart from +modified paths mentioned above) is that you should replace this fragment:

<!-- Location of the resources directory, where JS libs and icons are stored -->
+<xsl:param name="resources-uri">resources</xsl:param>
+

with this one:

<!-- Location of the resources directories, where JS libs and icons are stored -->
+<xsl:param name="dojo-resources"/>
+<xsl:param name="forms-resources"/>
+

Javascript adjustments (for widgets authors)

If you happened to write custom widget you probably will need to adjust your +code, also. Unfortunately, this step can be more troublesome than others and can +demand from you better understanding of the changes that has been incorporated +into Forms code during refactoring process. Here, the most important issues will +be highlighted taking as example migration of MultiValueEditor from Cocoon's +distribution.

+Here is the diff:

Index: src/main/resources/org/apache/cocoon/forms/resources/js/MultiValueEditor.js
+===================================================================
+--- src/main/resources/org/apache/cocoon/forms/resources/js/MultiValueEditor.js	(wersja 517778)
++++ src/main/resources/org/apache/cocoon/forms/resources/js/MultiValueEditor.js	(wersja 517779)
+@@ -39,9 +39,9 @@
+ 
+         cformsIdPrefix: "id-prefix-not-set",
+ 
+-        resourcesUri: cocoon.resourcesUri, // to make this available to the template
++        formsResourcesUri: cocoon.formsResourcesUri, // to make this available to the template
+ 
+-        templatePath: cocoon.resourcesUri + "/forms/js/templates/MultiValueEditor.html",
++        templatePath: cocoon.formsResourcesUri + "/js/templates/MultiValueEditor.html",
+ 
+         fillInTemplate: function(args, frag) {
+             cocoon.forms.MultiValueEditor.superclass.fillInTemplate(this, args, frag);
+
+Index: src/main/resources/org/apache/cocoon/forms/resources/js/templates/MultiValueEditor.html
+===================================================================
+--- src/main/resources/org/apache/cocoon/forms/resources/js/templates/MultiValueEditor.html	(wersja 517778)
++++ src/main/resources/org/apache/cocoon/forms/resources/js/templates/MultiValueEditor.html	(wersja 517779)
+@@ -9,11 +9,11 @@
+         </select>
+       </td>
+       <td width="20px">
+-        <input dojoAttachPoint="deleteButton" type="image" src="${this.resourcesUri}/forms/img/delete.gif"/>
++        <input dojoAttachPoint="deleteButton" type="image" src="${this.formsResourcesUri}/img/delete.gif"/>
+         <br/>
+-        <input dojoAttachPoint="moveUpButton" type="image" src="${this.resourcesUri}/forms/img/move_up.gif"/>
++        <input dojoAttachPoint="moveUpButton" type="image" src="${this.formsResourcesUri}/img/move_up.gif"/>
+         <br/>
+-        <input dojoAttachPoint="moveDownButton" type="image" src="${this.resourcesUri}/forms/img/move_down.gif"/>
++        <input dojoAttachPoint="moveDownButton" type="image" src="${this.formsResourcesUri}/img/move_down.gif"/>
+         <br/>
+       </td>
+     </tr>
+

As you can see, there is no cocoon.resourcesUri property anymore. If +you put your own widget in Forms' resource tree, simply replace +cocoon.resourcesUri with cocoon.formsResourcesUri. Otherwise, +introduce your own property and set it's value to +"servlet:/resource/external/yourwidget/" or similar.

+If you use Forms URI, don't forget to remove redundant "/forms" prefix +(see example above).

Note: It has been removed because there is no universal +_cocoon/** matcher loading resources for all blocks (including Forms); +now every block is responsible on its own for loading its resources. Even more, +there is no universal pattern for resources URLs because blocks can be mounted +at different locations. You may think that situation is worse than it used to be +but it's not the case. If you think that I suggest to learn more about servlet +service framework.

If you have additional questions don't hesitate to ask for a help on user's +mailing list.

Sitemap adjustments

Obviously, you have to adjust your sitemap too to pass new parameters:

<map:transform src="resources/forms-samples-styling.xsl">
+  <map:parameter name="resources-uri" value="{request:contextPath}/_cocoon/resources"/>
+</map:transform>
+

should be replaced with:

<map:transform src="resources/forms-samples-styling.xsl">
+  <map:parameter name="dojo-resources" value="{servlet:ajax:/resource/external/dojo}"/>
+  <map:parameter name="forms-resources" value="{servlet:forms:/resource/external/forms}"/>
+</map:transform>
+

Of course you may have little bit different configuration. Above fragments +are mentioned for explanatory purpose.

Links with in servlet: scheme cannot be included in HTML code sent +to the browser thus you need to perform link rewriting step just before +serialization. In order to do that, you will need to add +servletLinkRewriting transformer as shown in this example:

     <map:match pattern="*-display-pipeline.jx">
+       <map:generate type="jx" src="forms/{1}_template.xml" label="content1">
+         <map:parameter name="locale" value="{flow-attribute:locale}"/>
+       </map:generate>
+       <map:transform type="browser-update"/><!-- AJAX-style form update -->
+       <map:transform type="i18n">
+         <map:parameter name="locale" value="{flow-attribute:locale}"/>
+       </map:transform>
+       <map:call resource="simple-page2html">
+         <map:parameter name="file" value="forms/{1}_template.xml"/>
+       </map:call>
+       <map:transform src="resources/forms-samples-styling.xsl">
+         <map:parameter name="dojo-resources" value="{servlet:ajax:/resource/external/dojo}"/>
+         <map:parameter name="forms-resources" value="{servlet:forms:/resource/external/forms}"/>
+         <map:parameter name="dojo-debug" value="true"/><!-- set to true to turn on dojo debugging in the Browser -->
+         <map:parameter name="dojo-locale" value="{flow-attr:locale}"/>
+       </map:transform>
+       <map:transform type="i18n">
+         <map:parameter name="locale" value="{flow-attribute:locale}"/>
+       </map:transform>
+
+       <map:transform type="servletLinkRewriter"/> <!-- here is the transformation step you will need to add -->
+
+       <map:select type="ajax-request">
+         <map:when test="true"><!-- sending a partial Browser Update -->
+            <map:select type="request-parameter">
+              <map:parameter name="parameter-name" value="dojo.transport"/>
+              <map:when test="iframe"><!-- sending BU via iFrameIO -->
+                <map:transform src="servlet:forms:/resource/internal/xsl/IframeTransport-bu-styling.xsl"/>
+                <map:serialize type="xhtml"/><!-- this is REALLY important -->
+              </map:when>
+              <map:otherwise><!-- sending BU via XHR -->
+                <map:serialize type="xml"/>
+              </map:otherwise>
+            </map:select>
+         </map:when>
+         <map:otherwise><!-- sending a complete page -->
+           <map:serialize type="html"/>
+         </map:otherwise>
+       </map:select>
+     </map:match>
+

You should add that transformer to all pipelines that transform Forms code +into HTML.

Also, this is last step of whole migration process. After performing all +steps you need to rebuild your block and clear browser cache to get everything +working as before refactoring and migration process.

See also

You may also be interested with AJAX migration +guide.

Errors and Improvements? If you see any errors or potential improvements in this document please help + us: View, Edit or comment on the latest development version (registration required). +
+
+ + + + + + Added: cocoon/site/site/2.2/blocks/forms/1.0/475_1_1.html URL: http://svn.apache.org/viewvc/cocoon/site/site/2.2/blocks/forms/1.0/475_1_1.html?rev=580139&view=auto ============================================================================== --- cocoon/site/site/2.2/blocks/forms/1.0/475_1_1.html (added) +++ cocoon/site/site/2.2/blocks/forms/1.0/475_1_1.html Thu Sep 27 12:56:05 2007 @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + Cocoon Forms + + + + + + + +
+

Apache » Cocoon »

+
+ + + +
+ + +

Template Transformer

Introduction

The Forms Template Transformer can execute the CForms +template tags.

Usage

For how to declare this transformer and how to embed it in a pipeline, see +the Cocoon samples (the lazy doc writer approach).

Special features of the forms transformer

Where the forms transformer looks for the form instance object

Each time the forms transformer encounters a ft:form-template element, it +will try to retrieve a CForms form instance object. It looks for it in the +following locations:

    +
  1. if the ft:form-template element has a location attribute, then the value of +that attribute will be evaluated as a JXPath expression. The result of this +expression should be the form object.
  2. +
  3. if a parameter called "attribute-name" was supplied to the forms transformer +in the sitemap, then the forms transformer will try to find the form in the +request attribute with that name. (request attributes are a temporary storage +area that exists for the duration of one request and is often used to +communicate objects between different sitemap components such as actions and +transformers)
  4. +
  5. finally, the forms transformer will look if a CForms form was supplied from +a flowscript using the key "CocoonFormsInstance".
  6. +
If the form is not found at any of these locations, an exception is thrown. +For example, if your form object is stored in the session using the key +"myform", then following expression in the location attribute can be used to +retrieve it:
<ft:form-template location="getAttribute($session, 'myform')" ...
If you'd like to retrieve the key "myform" from a parameters specified in the +sitemap, say one called "sessionattr", then the following can be used:
<ft:form-template location="getAttribute($session,
+                            getParameter($parameters, 'sessionattr'))" ...

As mentioned before, ft:form-template elements cannot be nested, but you can +have multiple ft:form-template elements on one page. Together with the location +attribute, this can be used to handle multiple forms occuring on one template. +

Action attribute on ft:form-template

The forms transformer supports the execution of JXPath expressions that occur +in the action attribute of the ft:form-template element. This makes it possible +to embed the continuation ID in that attribute.

For example:

<ft:form-template action="#{$cocoon/continuation/id}.continue" ...

The following objects are available in the JXPath context via the cocoon +object: continuation, requests, session and parameters. The context of the +JXPath expression is the map passed on from the flowscript (if any).

Note that the JXTemplate-based form-template-tag-implementation of course +also supports this, as this is a native feature of JXTemplate.

Errors and Improvements? If you see any errors or potential improvements in this document please help + us: View, Edit or comment on the latest development version (registration required). +
+
+ + + + + + Added: cocoon/site/site/2.2/blocks/forms/1.0/476_1_1.html URL: http://svn.apache.org/viewvc/cocoon/site/site/2.2/blocks/forms/1.0/476_1_1.html?rev=580139&view=auto ============================================================================== --- cocoon/site/site/2.2/blocks/forms/1.0/476_1_1.html (added) +++ cocoon/site/site/2.2/blocks/forms/1.0/476_1_1.html Thu Sep 27 12:56:05 2007 @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + Cocoon Forms + + + + + + + +
+

Apache » Cocoon »

+
+ + + +
+ + +

Forms Generator

Concept

The FormsGenerator is a Cocoon generator that generates an XML representation +of a form instance object.

Errors and Improvements? If you see any errors or potential improvements in this document please help + us: View, Edit or comment on the latest development version (registration required). +
+
+ + + + + + Added: cocoon/site/site/2.2/blocks/forms/1.0/477_1_1.html URL: http://svn.apache.org/viewvc/cocoon/site/site/2.2/blocks/forms/1.0/477_1_1.html?rev=580139&view=auto ============================================================================== --- cocoon/site/site/2.2/blocks/forms/1.0/477_1_1.html (added) +++ cocoon/site/site/2.2/blocks/forms/1.0/477_1_1.html Thu Sep 27 12:56:05 2007 @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + Cocoon Forms + + + + + + + +
+

Apache » Cocoon »

+
+ + + +
+ + +

Action widget

Concept

Used to trigger an action event on the server side. Usually presented as a +button the user can press (though this is not required). When an action widget +was activated, validation will not be performed. This is because usually it +would be strange to have other fields validated when the user's intention wasn't +really to submit the form. If you want validation to happen, use the +submit widget. After pressing an action button, the form +will normally always be redisplayed, unless the event handling code explicitely +disables this (by using the method endFormProcessing method on the +Form object).

Definition

<fd:action id="..." command="..." state="...">
+  <fd:label>...</fd:label>
+  <fd:help>...</fd:help>
+  <fd:hint>...</fd:hint>
+  <fd:on-action>
+    [...]
+  </fd:on-action>
+  <fd:on-create>
+    [..]
+  </fd:on-create>
+  <fd:attributes>
+    <fd:attribute name="..." value="..."/>
+  </fd:attributes>
+</fd:action>

The command attribute specifies a name that will be part of +the event generated by this widget. This can sometimes be useful. For example, +on the Repeater action and Row +action it indicates what to do. Previously this attribute was called +action-command (now deprecated).

For more information on how event handlers are defined, see +Event Handling. The interface to be implemented for Java +event listeners is org.apache.cocoon.forms.event.ActionListener. The +WidgetEvent subclass is org.apache.cocoon.forms.event.ActionEvent.

Template

An action widget is inserted in a template using the ft:widget tag:

<ft:widget id="..."/>
+

Styling (default HTML XSL)

By default an action widget is shown as a button.

To render the action widget as an image:

<ft:widget id="...">
+  <fi:styling type="image" src="foo.gif">
+</ft:widget>
+

To render the action widget as a link:

<ft:widget id="...">
+  <fi:styling type="link">
+</ft:widget>
Errors and Improvements? If you see any errors or potential improvements in this document please help + us: View, Edit or comment on the latest development version (registration required). +
+
+ + + + + + Added: cocoon/site/site/2.2/blocks/forms/1.0/478_1_1.html URL: http://svn.apache.org/viewvc/cocoon/site/site/2.2/blocks/forms/1.0/478_1_1.html?rev=580139&view=auto ============================================================================== --- cocoon/site/site/2.2/blocks/forms/1.0/478_1_1.html (added) +++ cocoon/site/site/2.2/blocks/forms/1.0/478_1_1.html Thu Sep 27 12:56:05 2007 @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + Cocoon Forms + + + + + + + +
+

Apache » Cocoon »

+
+ + + +
+ + +

A Simple Example

A simple CForms example

In this example we will show how to create a simple registration form using +CForms and flowscript. We will follow to following steps:

    +
  1. Create a form definition file
  2. +
  3. Create a template file
  4. +
  5. Write a bit of flowscript
  6. +
  7. Add some pipelines to the sitemap
  8. +
You can try this sample out on a default Cocoon install. In the webapp +directory (build/webapp), create a new subdirectory, for example called +myformtest. In there, create the files as outlined in this sample.Here is a screenshot of the form we're going to create:forms_registrationform

Create a form definition file

Below the form definition file is displayed, +registration_definition.xml. This lists all the widgets in the form, +together with their configuration information.
<fd:form
+  xmlns:fd="http://apache.org/cocoon/forms/1.0#definition">
+
+  <fd:widgets>
+    <fd:field id="name" required="true">
+      <fd:label>Name:</fd:label>
+      <fd:datatype base="string"/>
+      <fd:validation>
+        <fd:length min="2"/>
+      </fd:validation>
+    </fd:field>
+
+    <fd:field id="email" required="true">
+      <fd:label>Email address:</fd:label>
+      <fd:datatype base="string"/>
+      <fd:validation>
+        <fd:email/>
+      </fd:validation>
+    </fd:field>
+
+    <fd:field id="age">
+      <fd:label>Your age:</fd:label>
+      <fd:datatype base="long"/>
+      <fd:validation>
+        <fd:range min="0" max="150"/>
+      </fd:validation>
+    </fd:field>
+
+    <fd:field id="password" required="true">
+      <fd:label>Password:</fd:label>
+      <fd:datatype base="string"/>
+      <fd:validation>
+        <fd:length min="5" max="20"/>
+      </fd:validation>
+    </fd:field>
+
+    <fd:field id="confirmPassword" required="true">
+      <fd:label>Re-enter password:</fd:label>
+      <fd:datatype base="string"/>
+      <fd:validation>
+        <fd:assert test="password = confirmPassword">
+          <fd:failmessage>The two passwords are not equal.</fd:failmessage>
+        </fd:assert>
+      </fd:validation>
+    </fd:field>
+
+    <fd:booleanfield id="spam">
+      <fd:label>Send me spam</fd:label>
+    </fd:booleanfield>
+  </fd:widgets>
+
+</fd:form>
+

All elements are in the Forms Definition namespace: fd.

Every definition file has a <fd:form> element as the root +element.

The child widgets of the form are defined inside the +<fd:widgets> element. As you can see, most of the widgets are +field widgets. The field widget is the most important widget in CForms. It is +very flexible because it can be associated with different datatypes and with a +selection list. See the reference docs for more information on this and other +widgets.

A nice feature is that the fd:label tags can contain mixed content. +On the one hand, this can be used to provide rich formatting in the label. But +it also enables you to put i18n-elements in there, to be interpreted by the +I18nTransformer. This way, internationalisation is done using standard Cocoon +techniques.

Create a template file

Here is the template for our registration form example, +registration_template.xml:

<html xmlns:ft="http://apache.org/cocoon/forms/1.0#template"
+  xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
+  xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">
+
+  <jx:import uri="resource://org/apache/cocoon/forms/generation/jx-macros.xml"/>
+
+  <head>
+    <title>Registration form</title>
+  </head>
+  <body>
+    <h1>Registration</h1>
+    <ft:form-template action="#{$continuation/id}.continue" method="POST">
+      <ft:widget-label id="name"/>
+      <ft:widget id="name"/>
+      <br/>
+      <ft:widget-label id="email"/>
+      <ft:widget id="email"/>
+      <br/>
+      <ft:widget-label id="age"/>
+      <ft:widget id="age"/>
+      <br/>
+      <ft:widget-label id="password"/>
+      <ft:widget id="password">
+        <fi:styling type="password"/>
+      </ft:widget>
+      <br/>
+      <ft:widget-label id="confirmPassword"/>
+      <ft:widget id="confirmPassword">
+        <fi:styling type="password"/>
+      </ft:widget>
+      <br/>
+      <ft:widget id="spam"/>
+      <ft:widget-label id="spam"/>
+      <br/>
+
+      <input type="submit"/>
+    </ft:form-template>
+  </body>
+</html>

The CForms-specific elements here are in the "Forms Template" namespace: +ft.

First, jx:import is used to import the CForms macros which execute the +elements in the ft namespace.

The <ft:widget-label> tag will cause the label of a widget to +be inserted at the location of the tag. The <ft:widget> tag will +cause the XML representation of a widget to be inserted at the location of that +tag. The inserted XML will be in the "Forms Instance" namespace: +fi.

The XML representation of the widget will then be translated to HTML by an +XSLT stylesheet (forms-samples-styling.xsl in our case -- see sitemap snippets +below). This XSLT only has to handle individual widgets, and not the page as a +whole, and is thus not specific for one form but can be reused across forms.

For certain widgets it may be necessary to provide extra presentation hints, +such as the width of a text box, the style of a selection list (drop down, radio +buttons, ...) or class and style attribute values. This can be done by putting a +fi:styling element inside the ft:widget element. This element is in the fi +namespace because it will be copied literally. The attributes and/or content of +the fi:styling element depend on what is supported by the particular stylesheet +used.

As an alternative to the template approach, you could also use the +FormsGenerator, which will generate an XML representation of the whole form, and +style that with a custom-written XSLT. For most users we recommend the template +approach though.

Write a bit of flowscript

Flowscript is Cocoon's solution to handling the flow of a web interaction. It +is based on the concept of continuations. If you don't know yet about +continuations and flowscript, learn about it here.

Here's the flowscript for our example, registration.js:

cocoon.load("resource://org/apache/cocoon/forms/flow/javascript/Form.js");
+
+function registration() {
+    var form = new Form("registration_definition.xml");
+
+    form.showForm("registration-display-pipeline");
+
+    var viewData = { "username" : form.getChild("name").getValue() }
+    cocoon.sendPage("registration-success-pipeline", viewData);
+}

The flowscript works as follows:

First we create a Form object, specifying the form definition file +to be used. The Form object is actually a javascript wrapper around the "real" +Java form instance object.

Then the showForm function is called on the form object. This will +(re)display the form to the user until validation of the form succeeded. As +parameter to the showForm function, we pass the sitemap pipeline to be used to +display the form.

Finally we get some data from the form (the entered name), and call a sitemap +pipeline to display this data. This pipeline is based on the JXTemplate +generator.

Add some pipelines to the sitemap

Here is the sitemap we need, sitemap.xmap:

<?xml version="1.0"?>
+<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
+
+  <map:components>
+    <map:transformers default="xslt">
+      <map:transformer name="i18n"
+        src="org.apache.cocoon.transformation.I18nTransformer">
+        <catalogues default="forms">
+          <catalogue id="forms" name="messages"
+            location="resource://org/apache/cocoon/forms/system/i18n"/>
+        </catalogues>
+        <cache-at-startup>true</cache-at-startup>
+      </map:transformer>
+    </map:transformers>
+  </map:components>
+
+  <map:views>
+  </map:views>
+
+  <map:resources>
+  </map:resources>
+
+  <map:flow language="javascript">
+    <map:script src="registration.js"/>
+  </map:flow>
+
+  <map:pipelines>
+
+   <map:pipeline>
+     <map:match pattern="registration">
+       <map:call function="registration"/>
+     </map:match>
+
+     <map:match pattern="*.continue">
+       <map:call continuation="{1}"/>
+     </map:match>
+
+     <map:match pattern="registration-display-pipeline">
+       <map:generate type="jx" src="registration_template.xml"/>
+       <map:transform type="i18n">
+         <map:parameter name="locale" value="en-US"/>
+       </map:transform>
+       <map:transform src="forms-samples-styling.xsl"/>
+       <map:serialize/>
+     </map:match>
+
+     <map:match pattern="registration-success-pipeline">
+       <map:generate type="jx" src="registration_success.jx"/>
+       <map:serialize/>
+     </map:match>
+
+     <map:match pattern="resources/*/**">
+       <map:read src="resource://org/apache/cocoon/{1}/resources/{2}"/>
+     </map:match>
+
+   </map:pipeline>
+
+ </map:pipelines>
+
+</map:sitemap>
+

Note the following things:

    +
  • The i18n transformer is configured so it knows about the forms messages. The +forms catalogue does not have to be the default one, but here it is the only one +and thus the default.
  • +
  • In the map:flow tag our flowscript file is declared.
  • +
  • Then we have the pipelines:
  • +
      +
    • The first two are for managing the flowscript: when someone hits the +registration URL, we call the registration function in our flowscript
    • +
    • When a form is submitted, it will be matched by the second matcher, +*.continue, which will continue the execution of the flowscript.
    • +
    • The third matcher is for displaying the form. Note the JXTemplate generator +is used so that the form template tags get interpreted.
    • +
    • The fourth pipeline is for showing the "success" page, again using the +JXTemplate generator, the contents of the registration_succcess.jx file is given +below.
    • +
    • The last one is for making default CForms resources available, such as +javascript libraries, CSS files and images.
    • +
    + +
As promised, here is the content of the registration_success.jx +file:
<?xml version="1.0"?>
+<html>
+  <head>
+    <title>Registration successful</title>
+  </head>
+  <body>
+    Registration was successful for ${username}!
+  </body>
+</html>
+
One last thing you need to do is to copy the following file, which you find +in the Cocoon download, to your test directory:
src/blocks/forms/samples/resources/forms-samples-styling.xsl

Try it out

If you have created all the files mentioned above, you can now try out this +sample by browsing to:
http://localhost:8888/myformtest/registration
+
Try entering incorrect data and see what it does.

Next steps

The example we have studied here is quite simple. It might seem elaborate for +a simple form (though notice you didn't have to write any Java for all of this, +nor to restart Cocoon), but adding more complexity to the form is now simply a +matter of adding more widgets, custom validation logic, event handlers, etc. To +have a feel for the power of CForms, take a look at the examples included +included in the Forms block.
Errors and Improvements? If you see any errors or potential improvements in this document please help + us: View, Edit or comment on the latest development version (registration required). +
+
+ + + + + +