A document has been updated:

http://cocoon.zones.apache.org/daisy/documentation/750.html

Document ID: 750
Branch: main
Language: default
Name: Ajax (unchanged)
Document Type: Cocoon Document (unchanged)
Updated on: 10/23/05 8:58:06 PM
Updated by: Sylvain Wallez

A new version has been created, state: publish

Parts
=====
Content
-------
This part has been updated.
Mime type: text/xml (unchanged)
File name:  (unchanged)
Size: 8090 bytes (previous version: 597 bytes)
Content diff:
    <html>
    <body>
    
--- <p>Starting with Cocoon 2.1.8, CForms offers (mostly) transparent Ajax 
support.
--- Ajax is the catchy name for using Javascript and assynchronous web server
--- communication to offer a better user experience in the browser. Within 
CForms,
--- this allows for example to update only the parts of the page that require
--- updating, without refreshing the entire page. Enabling Ajax for existing 
CForms
--- is straightforward.</p>
+++ <h1>Introduction</h1>
    
--- <p>For more information, see the
+++ <p><a href="http://en.wikipedia.org/wiki/AJAX";>Ajax</a> is a catchy name for
+++ using JavaScript client-side code that communicates asynchronously with the
+++ server, thus allowing to escape the traditional web model where each button
+++ click translates to a full page reload.</p>
+++ 
+++ <p>Cocoon Forms has a number of features that allow the building of
+++ highly-interactive forms, such as validation, value-change listeners, 
intra-form
+++ actions, repeaters, etc. Having a full page reload for each action doesn't
+++ provide a good user experience and puts an unncessary load on the 
server.</p>
+++ 
+++ <p>Starting with Cocoon 2.1.8, Cocoon Forms offers (mostly) transparent Ajax
+++ support. What this means is that when a form is submitted, this happens in 
the
+++ background and only those parts of the form that actually changed are 
updated on
+++ the page. Full-page reload only happens when interaction with the form is
+++ finished.</p>
+++ 
+++ <h1>How to activate Ajax on your forms?</h1>
+++ 
+++ <h2>The "ajax" attribute</h2>
+++ 
+++ <p>Activating Ajax mode on your forms is straightforward: just add
+++ <tt>ajax="true"</tt> on the <tt>&lt;ft:form-template&gt;</tt> element in 
your
+++ form template:</p>
+++ 
+++ <pre>&lt;ft:form-template action="continue" method="POST" 
<strong>ajax="true"</strong>&gt;
+++   &lt;ft:widget id="email"/&gt;
+++   .../...
+++ &lt;/ft:form-template&gt;
+++ </pre>
+++ 
+++ <p>There are a number of things to take care of though for the Ajax mode to
+++ function properly.</p>
+++ 
+++ <h2>Use the Template Generator</h2>
+++ 
+++ <p>As of version 2.1.8, Ajax support is implemented only in the JXTemplate
+++ version of the Forms Template language.</p>
+++ 
+++ <h2>Container widgets must enclose a container element</h2>
+++ 
+++ <p>The Ajax support of Cocoon Forms works by sending partial page updates 
to the
+++ browser. This requires the representation of widgets to be contained in a 
single
+++ element, which becomes the "replacement unit" for that widget.</p>
+++ 
+++ <p>The styling stylesheets take care of this for terminal widgets such as 
fields
+++ and actions, but not for container widgets whose layout are completely 
defined
+++ by the page template. Concretely, this means that 
<tt>&lt;ft:repeater&gt;</tt>,
+++ <tt>&lt;ft:group&gt;</tt> and <tt>&lt;ft:union</tt>&gt; instructions must
+++ contain a single element such as HTML <tt>&lt;div&gt;</tt>,
+++ <tt>&lt;able&gt;</tt>, <tt>&lt;span&gt;</tt>, etc.</p>
+++ 
+++ <pre>&lt;ft:group id="info"&gt;
+++   &lt;div&gt;
+++     &lt;p&gt;&lt;ft:widget id="foo"/&gt;&lt;/p&gt;
+++     &lt;p&gt;&lt;ft:widget id="bar"/&gt;&lt;/p&gt;
+++   &lt;/div&gt;
+++ &lt;/ft:group&gt;
+++ </pre>
+++ 
+++ <p>The formatting pipeline with then take care of adding an <tt>id</tt>
+++ attribute on the container element so that it can be found and updated in 
the
+++ displayed page.</p>
+++ 
+++ <h2>Use &lt;ft:repeater&gt; instead of &lt;ft:repeater-widget&gt;</h2>
+++ 
+++ <p>A problem with the existing <tt>&lt;ft:repeater-widget&gt;</tt> 
instruction
+++ is that it handles two different kinds of widgets, the repeater itself and 
its
+++ rows. This has the drawback of not allowing individual refresh of rows and 
does
+++ not allow the template system to identify a unique element that contains the
+++ repeater, as explained above.</p>
+++ 
+++ <p>Starting with Cocoon 2.1.8, the template for repeaters involve two
+++ instructions, <tt>&lt;ft:repeater&gt;</tt> and
+++ <tt>&lt;ft:repeater-rows&gt;</tt>:</p>
+++ 
+++ <ul>
+++ <li><tt>&lt;ft:repeater&gt;</tt> starts the repeater template, and sets the
+++ repeater as the context widget. This instruction must contain a single 
element.
+++ </li>
+++ <li><tt>&lt;ft:repeater-rows&gt;</tt> iterates through all rows in the 
repeater.
+++ Again, and because a row is a container widget, this instruction must 
contain a
+++ single element. Note that <tt>&lt;ft:repeater-rows&gt;</tt> has to be a
+++ descendant of <tt>&lt;ft:repeater&gt;</tt>, but does not need to be a direct
+++ child and that any number of document elements can enclose
+++ <tt>&lt;ft:repeater-rows&gt;</tt> (not form templates instruction 
though).</li>
+++ </ul>
+++ 
+++ <p>Remember also that the JXTemplate macros define the <tt>repeater</tt> and
+++ <tt>repeaterLoop</tt> variables in <tt>&lt;ft:repeater&gt;</tt> and
+++ <tt>&lt;ft:repeater-rows&gt;</tt> respectively that allow for some powerful
+++ conditional templates.</p>
+++ 
+++ <p>Here's a complete example, which is what you will have in many real-world
+++ situations:</p>
+++ 
+++ <pre>Here are your contacts:
+++ 
+++ &lt;ft:repeater id="contacts"&gt;
+++   &lt;jx:choose&gt;
+++ 
+++     &lt;!-- formatting of an empty "contacts" --&gt;
+++     &lt;jx:when test="${repeater.size == 0}"&gt;
+++       &lt;span&gt;
+++         You have no contacts.
+++         &lt;ft:widget id="../add-contact"/&gt;
+++       &lt;/span&gt;
+++     &lt;/jx:when&gt;
+++ 
+++     &lt;!-- formatting for a non-empty "contacts" --&gt;
+++     &lt;jx:otherwise&gt;
+++       &lt;div&gt;
+++         &lt;table&gt;
+++           &lt;tr&gt;
+++             &lt;th&gt;First name&lt;/th&gt;&lt;th&gt;Last 
name&lt;/th&gt;&lt;th&gt;Email&lt;/th&gt;
+++           &lt;/tr&gt;
+++           &lt;ft:repeater-rows&gt;
+++             &lt;!-- container element for rows --&gt;
+++             &lt;tr class="row-${repeaterLoop.index % 2}"&gt; 
+++               &lt;ft:widget id="firstname"/&gt;
+++               &lt;ft:widget id="lastname"/&gt;
+++               &lt;ft:widget id="email"/&gt;
+++               &lt;ft:widget id="select"/&gt;
+++             &lt;/tr&gt;
+++           &lt;/ft:repeater-rows&gt;
+++         &lt;/table&gt;
+++         &lt;ft:widget id="../add-contact"/&gt;
+++         &lt;ft:widget id="../delete-contact"/&gt;
+++       &lt;/div&gt;
+++     &lt;/jx:otherwise&gt;
+++ 
+++   &lt;/jx:choose&gt;
+++ &lt;/ft:repeater&gt;
+++ 
+++ &lt;ft:widget id="ok"/&gt;
+++ </pre>
+++ 
+++ <p>This example shows some conditional formatting (using JXTemplate) 
depending
+++ if the repeater is empty or not. In the two cases, the action widgets that 
allow
+++ to remove and delete rows are added within the repeater template. We use the
+++ <tt>"../add-contact"</tt> notation (<tt>"../"</tt> goes back to the parent
+++ widget) as these actions are defined as siblings of the repeater in the form
+++ definition, but we want them to be included in the repeater's conditional
+++ templates. We therefore need to "escape" the repeater to lookup its 
siblings.
+++ </p>
+++ 
+++ <p>Notice the <tt>&lt;span&gt;</tt> element when the repeater is empty. 
Even it
+++ we don't really need it from the page layout point of view, it is required 
to
+++ have a single element for Ajax updates when the user adds a contact.</p>
+++ 
+++ <p>Notice also the <tt>&lt;div&gt;</tt> element when the repeater is not 
empty.
+++ We cannot use the <tt>&lt;table&gt;</tt> that encloses rows, as again, we 
want
+++ to include the <tt>"add-contact"</tt> and <tt>"delete-contacts"</tt> 
actions in
+++ the conditional template. We therefore need an enclosing element for the 
table
+++ and the actions.</p>
+++ 
+++ <p>The <tt>&lt;ft:repeater-rows&gt;</tt> doesn't need anything special as 
the
+++ <tt>&lt;td&gt;</tt> serves as the container. The
+++ <tt>class="row-${repeaterLoop.index % 2}"</tt> allows the generation of
+++ alternating colors of rows, as even rows will have <tt>class="row-0"</tt> 
and
+++ odd rows will have <tt>class="row-1"</tt>.</p>
+++ 
+++ <h2>Using Ajax in portals and aggregations</h2>
+++ 
+++ <p>Portals do a lot of URL rewriting to ensure that only aggregated portal 
pages
+++ are displayed, even if individual portlets use their own URLs without caring
+++ about being integrating in a portal. This rewriting defeats the Ajax system 
that
+++ posts the form in the background using the <tt>&lt;form&gt;</tt>'s
+++ <tt>action</tt> attribute, which is rewritten by the portal.</p>
+++ 
+++ <p>To allow the Ajax system to function in a portal, you must add an 
additional
+++ <tt>ajax-action</tt> attribute on <tt>&lt;ft:form-template&gt;</tt>. When
+++ present, this attribute's value is where Ajax requests will be posted 
instead of
+++ the value of <tt>action</tt>.</p>
+++ 
+++ <pre>&lt;ft:form-template action="aggregation" 
ajax-action="continue-form"&gt;
+++   .../...
+++ &lt;/ft:form-template&gt;</pre>
+++ 
+++ <p>Note that because of the portal's URL rewriting, the two attributes will
+++ often have the same values in the template.</p>
+++ 
+++ <h1>The form display pipeline for Ajax</h1>
+++ 
+++ <p>TBC</p>
+++ 
+++ <p>You can also find additional information in the
    <a href="http://www.cocoongt.org/Slides-and-recordings.html";>Ajax 
presentation
    from the Cocoon GetTogether 2005</a>.</p>
    
(2 equal lines skipped)


Fields
======
no changes

Links
=====
no changes

Custom Fields
=============
no changes

Collections
===========
no changes