apache > cocoon

Improving the simple sample

This section describes some possible improvements to the simple sample.

Automatic layouting

A very common way of layouting a form is in a table with two columns: the left column contains the labels, the right column the input fields. The CForms XSL stylesheets support some tags to do this automatically for you. Here is the template for the simple sample, using automatic two-column styling:

<html xmlns:ft="http://apache.org/cocoon/forms/1.0#template"

  <jx:import uri="resource://org/apache/cocoon/forms/generation/jx-macros.xml"/>

    <title>Registration form</title>
    <ft:form-template action="#{$continuation/id}.continue" method="POST">
        <fi:styling layout="columns"/>
          <ft:widget id="name"/>
          <ft:widget id="email"/>
          <ft:widget id="age"/>
          <ft:widget id="password">
            <fi:styling type="password"/>
          <ft:widget id="confirmPassword">
            <fi:styling type="password"/>
          <ft:widget id="spam"/>
      <input type="submit"/>

As you see, it is no longer needed to use the ft:widget-label tags. Furthermore, the stylesheets will properly use the HTML label tag to associate the label with the input field.

Other supported stylings include "tabs" (for tabbed panes), "choice" (similar to tabs but with a dropdown to switch), "fieldset" (groups the fields in a frame with a label). See the CForms samples for examples of how to use them.

Using i18n

As mentioned before, you can internationalize the form labels by embedding i18n tags that will be handled by the i18n transformer. Let's look at the concrete steps to achieve this.

First, the form definition. Here we need to add the declaration of the i18n namespace, and for now we'll just apply i18n for the name field. This is done as follows:


    <fd:field id="name" required="true">
      <fd:label><i18n:text key="name"/>:</fd:label>
      <fd:datatype base="string"/>
        <fd:length min="2"/>

Then, the resource bundle. Resource bundles for the i18n transformer are in an XML format. Create a subdirectory called i18n and put a file called messages.xml in it, containing the following:

<?xml version="1.0"?>
  <message key="name">Name</message>

The only thing left now is to change the configuration of the i18n transformer to make it aware of this resource bundle. Change the configuration of the i18n transformer in the sitemap as follows:

      <map:transformer name="i18n"
        <catalogues default="mymessages">
          <catalogue id="mymessages" name="messages" location="i18n"/>
          <catalogue id="forms" name="messages"

The location attribute of the catalogue is relative to the location of the sitemap, so the value i18n refers to the subdirectory you created in the previous step. As we did not mention the catalogue explicitely on the i18n:text element, we need to make it the default (the forms catalogue does not need to be the default). For more information on this see the i18n transformer documentation.

If you now try the sample again, everything should work as before; you should still see the "Name" label.

But now we still need to tell the i18n transformer what locale to use. To make our explanation more complete, we should not only tell the i18n transformer what locale to use, but the same locale should typically also be used when parsing form data and formatting form data for output (this does not matter for string fields, but important for dates and numbers). This can be done as follows. In the flowscript (registration.js), specify a locale property on the form. Let us take french as an example:

    var form = new Form("registration.xml");
    form.locale = new java.util.Locale("fr");

The locale you specify here will also be automatically added to the viewData for the pipeline when calling showForm.

In the sitemap, we need to pass the locale to the template generator and the i18n transformer:

     <map:match pattern="registration-display-pipeline">
       <map:generate type="jx" src="registration_template.xml">
         <map:parameter name="locale" value="{flow-attr:locale}"/>
       <map:transform type="i18n">
         <map:parameter name="locale" value="{flow-attr:locale}"/>
       <map:transform src="forms-samples-styling.xsl"/>

The "flow-attr" input module is used to retrieve values from the viewData.

Finally, create a french resource bundle: i18n/messages_fr.xml:

<?xml version="1.0"?>
  <message key="name">Nom</message>

If you now try the registration sample again, "Name" should be replaced by "Nom".