------
Ajax/DHTML Guide - Basics
------
Jesse Kuhnert
------
24 June 2007
------
Ajax Development Basics
The overall concept behind the majority of built in AJAX functionality in Tapestry is that everything should work exactly the same way in your pages/components
in AJAX requests as it does during normal page rendering. There are a few corner cases that have no real intuitive XHR equivalent which we will discuss as
well.
* Including JavaScript in your HTML Template
One of the first things you will need to do is make sure you have the necessary javascript includes. Tapestry makes extensive use of the {{{http://dojotoolkit.org}Dojo}}
javascript toolkit and provides a couple of options for including it for you automatically via the {{{../components/general/shell.html}Shell}} or
{{{../components/general/scriptincludes.html}ScriptIncludes}} components. An example of defining a basic outer layer using the {{{../components/general/shell.html}Shell}}
component would look like:
+-------------------------------------------------------------------------------------------------------------
Basic javascript inclusion sample.
+-------------------------------------------------------------------------------------------------------------
* Updating Components: The universal updateComponents parameter
One of the most frequently used pieces of ajax functionality is the <<>> parameter that is now implemented by all of the core Tapestry
components - where it makes sense. Some of the more familiar of these are {{{../components/link/directlink.html}DirectLink}}, {{{../components/form/linksubmit.html}LinkSubmit}},
{{{../components/form/form.html}Form}}, {{{../components/form/imagesubmit.html}ImageSubmit}} and {{{../components/form/submit.html}Submit}}. We'll build on our previous
example and use the {{{../components/link/directlink.html}DirectLink}} component to refresh a current time display.
+-------------------------------------------------------------------------------------------------------------
..
Basic javascript inclusion sample.
Refresh time.
..
+-------------------------------------------------------------------------------------------------------------
The corresponding java page class:
+-------------------------------------------------------------------------------------------------------------
..
public abstract BasicAjax extends BasePage {
public abstract void setTime(Date time);
public void setTime()
{
setTime(new java.util.Date());
}
}
+-------------------------------------------------------------------------------------------------------------
That's it! Building and running this small example should be all you need to start using the very basic AJAX functionality provided by Tapestry.
** updateComponents == IComponent.getClientId()
There are a few subtle things happening here that may not be apparent at first glance. One of the more important changes in Tapestry 4.1.x was the addition of
the {{{../apidocs/org/apache/tapestry/IComponent.html#getClientId()}IComponent.getClientId()}} method to all component classes. When dealing with client side javascript
functionality the unique client side element id of the html elements your components generate becomes very important. What this method gives you is the unique element id
attribute that will be written for any given component depending on the context in which you call it.
If you are in a {{{../components/general/for.html}For}} loop then the <<>> will automatically be incremented for each loop and always represent the unique
value of the component. The same semantics work whether in {{{../components/form/form.html}Forms}} / {{{../components/general/for.html}For}} or any other nested
type of structure. This has been one of key changes in the API that has made the AJAX functionality provided easier to work with.
In our example the <<>> parameter given made use of the new smart auto binding functionality added to the framework recently, but you could write
the equivalent parameter using an ognl expression as well:
+-------------------------------------------------------------------------------------------------------------
Refresh time
+-------------------------------------------------------------------------------------------------------------
Things can get a lot uglier once you start trying to update multiple components:
+-------------------------------------------------------------------------------------------------------------
Refresh time
+-------------------------------------------------------------------------------------------------------------
The much easier simple string list <<>> is not only shorter / easier to understand but also more efficient and robust
in many different circumstances. For instance, the auto binding functionality would be able to detect that you were trying to update a component contained within
one of your own custom components as well as a component on the page containing your component and wire up and find all the correct <<>> values for you
automatically.
The thing to walk away with here is that in 98% of the cases you run in to this style of <<>> syntax is the way to go:
+-------------------------------------------------------------------------------------------------------------
Refresh time
+-------------------------------------------------------------------------------------------------------------
** How clientId values are generated
The actual value that is output by a component is determined by a number of rules depending on the context and type of component involved. Of course, no id will
be generated at all if your custom components don't call the new
{{{../apidocs/org/apache/tapestry/AbstractComponent.html#renderIdAttribute(org.apache.tapestry.IMarkupWriter,%20org.apache.tapestry.IRequestCycle)}AbstractComponent.renderIdAttribute(IMarkupWriter, IRequestCycle)}}
method provided in the base <<>> superclass that most components derive from. When that method is called the rules for determining what value to render out
in to the generated html element are evaluated in this order:
[[1]] <> - If the definition of the component being rendered had an informal <<>> parameter specified that will
take higher precendence than anything else. It may eventually end up being output as <<>> if your component is being rendered in a loop but
it will still use the id as the basis for its client side id values.
+----------------------------------------------
Content
+----------------------------------------------
[[1]] <