blob: 9ee9259883e3a1a960b1498b5523b3b64ab72cc7 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cocoon Forms: Template Transformer</title>
<link href="http://purl.org/DC/elements/1.0/" rel="schema.DC">
<meta content="The Apache Cocoon Team" name="DC.Creator">
</head>
<body>
<h1>Introduction</h1>
<p>The FormsTemplateTransformer (simply "forms transformer" from now on)
makes it possible to define the layout for your form without having
to write a separate XSLT for each form. If you prefer to do everything
with XSLT, you have also the option of using the
<a href="formsgenerator.html">FormsGenerator</a>. In general
we recommend to use the forms transformer though.</p>
<p>The basic principle is that the forms transformer will replace any
&lt;ft:widget id="xyz"/&gt; elements it encounters by the XML representation
of the corresponding widgets. These ft:widget elements can be embedded in
e.g. a HTML layout. So after passing this template through the forms transformer
you'll end up with HTML with here and there a piece of XML describing a widget.
This XML description contains all state information of the widget: its value,
validation errors, selection-list data if any, and so on. These
widget-XML-descriptions will then typically be translated to HTML by an XSLT.
This XSLT is then however not form-specific, as it simply needs to know how
to translate individual widgets to HTML, and does not have to create the
complete page layout. CForms contains just such an XSLT so you don't have
to write it yourself (except if you need to do heavy customisation).
The image below illustrates this process.</p>
<div align="center">
<img class="figure" alt="Forms Template Transformer illustration." src="images/forms_template_transformer.png"></div>
<h2>Where the forms transformer looks for the form instance object</h2>
<p>Each time the forms transformer encounters a ft:form-template element
(see further on), it will try to retrieve a CForms form instance object.
It looks for it in the following locations:</p>
<ol>
<li>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.</li>
<li>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)</li>
<li>finally, the forms transformer will look if a CForms form was supplied
from a flowscript using the key "CocoonFormsInstance".</li>
</ol>
<p>If the form is not found at any of these locations, an exception is thrown.</p>
<h1>Forms transformer element reference</h1>
<p>The elements to which the forms transformer reacts are all in
the "ft" (Forms Template) namespace, which is identified by the following URI:</p>
<pre class="code">http://apache.org/cocoon/forms/1.0#template</pre>
<p>These will generally be replaced by elements in the "fi" (Forms Instance)
namespace, which is identified by the following URI:</p>
<pre class="code">http://apache.org/cocoon/forms/1.0#instance</pre>
<h2>ft:form-template</h2>
<p>The ft:form-template element is always required; all other ft:*
elements should occur inside a ft:form-template element. As described
earlier, when the forms transformer encounters the ft:form-template
element it will try to look up the form instance object.</p>
<p>ft:form-template elements may not be nested.</p>
<p>The ft:form-template will by default copy over all attributes appearing
on it, except for one attribute called "location", and it will also take
special care of the action attribute.</p>
<p>The <strong>action</strong> attribute can contain JXPath expressions.
As with the JXTemplateGenerator, these JXPath expressions must be embedded
inside #{ and }. By allowing the use of JXPath expressions, you can
embed dynamic data in the action attribute. One of the most common uses
is to embed the continuation id (if you're using flowscript), for example:</p>
<pre class="code">&lt;ft:form-template action="#{$cocoon/continuation/id}.continue" ...</pre>
<p>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).</p>
<p>The <strong>location</strong> attribute, if present, is used to retrieve
the form instance object. The value of the location attribute should be a
JXPath expression, and is executed in the same context as the JXPath
expressions embedded in the action attribute.</p>
<p>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:</p>
<pre class="code">&lt;ft:form-template location="getAttribute($session, 'myform')" ...</pre>
<p>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:</p>
<pre class="code">&lt;ft:form-template location="getAttribute($session, getParameter($parameters, 'sessionattr'))" ...</pre>
<p>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.</p>
<h2>ft:widget</h2>
<p>The ft:widget element is replaced by the forms transformer by the XML
representation of a widget. Which widget is specified by the id attribute.
The ft:widget element can contain a fi:styling element containing parameters
to influence the styling process (the XSLT). The forms transformer will simply
copy the fi:styling element over to its output.</p>
<p>For example:</p>
<pre class="code">&lt;ft:widget id="pass"&gt;
&lt;fi:styling type="password"/&gt;
&lt;ft:widget/&gt;</pre>
<p>will be replaced by:</p>
<pre class="code">&lt;fi:field id="pass"&gt;
[... label, validation errors, ...]
&lt;fi:styling type="password"/&gt;
&lt;/fi:field&gt;</pre>
<p>Note: it is not recommended to use the older approach, i.e. without
the fi:styling element, anymore, since support for it will be dropped
at some point in the future. </p>
<h2>ft:widget-label</h2>
<p>The ft:widget-label element will be replaced by the forms transformer
with the label of a certain widget (specified by an id attribute).
The label will not be wrapped in another element.</p>
<h2>ft:continuation-id</h2>
<p>The ft:continuation-id element will be replaced by the forms transformer by:</p>
<pre class="code">&lt;fi:continuation-id&gt;
ID-of-the current-continuation
&lt;/fi:continuation-id&gt;</pre>
<p>This might be useful for embedding the continuation ID in a hidden form field, for example.</p>
<h2>Working with repeaters: ft:repeater-widget, ft:repeater-widget-label, ft:repeater-size</h2>
<p>The ft:repeater-widget element is similar to the ft:widget element but
provides special treatment for repeaters. The content of the ft:repeater-widget
element will be used as a template to generate each of the rows of the repeater.</p>
<p>The ft:repeater-widget-label element is used to retrieve the label of a
widget contained by a repeater. It requires two attributes: id (identifying
the repeater) and widget-id (identifying the widget in the repeater).</p>
<p>The ft:repeater-size element inserts an element &lt;fi:repeater-size id="..." size="..."/&gt;
containing the size (number of rows) of the repeater.</p>
<p>For an example of how this all fits together, take a look at the samples included in the forms block.</p>
</body>
</html>