------
Ajax/DHTML Guide - ResponseBuilder
------
Jesse Kuhnert
------
28 July 2006
------
Overview
One of the largest changes made to Tapestry 4.1 was the rendering cycle. Traditionally, responses were made
using one basic {{{../apidocs/org/apache/tapestry/IMarkupWriter.html}IMarkupWriter}} instance
to capture and render output back to the browser. <(this isn't entirely true, NullWriter instances are used
in some instances, like rewinding {{{../components/form/form.html}Form}} components)>
The new method looks basically the same on the surface, but rendering output is now managed by specific
{{{../apidocs/org/apache/tapestry/services/ResponseBuilder.html}ResponseBuilder}} instances,
depending on the type of request. These classes are responsible for calling
{{{../apidocs/org/apache/tapestry/AbstractComponent.html#render(org.apache.tapestry.IMarkupWriter,%20org.apache.tapestry.IRequestCycle)}AbstractComponent.html#render(IMarkupWriter writer, IRequestCycle cycle}}
for all component renders. They are also responsible for managing javascript output from script templates.
You can always get a reference to the correct {{{../apidocs/org/apache/tapestry/services/ResponseBuilder.html}ResponseBuilder}} for
the current request by calling <<>> on your {{{../apidocs/org/apache/tapestry/IRequestCycle.html}IRequestCycle}}
instance.
<> {{{../apidocs/org/apache/tapestry/services/ResponseBuilder.html}ResponseBuilder}},
{{{../apidocs/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.html}DojoAjaxResponseBuilder}},
{{{../apidocs/org/apache/tapestry/services/impl/JSONResponseBuilder.html}JSONResponseBuilder}}
* Using ResponseBuilder to dynamically update content
Based on the type of request made, one of the three available {{{../apidocs/org/apache/tapestry/services/ResponseBuilder.html}ResponseBuilder}}s
will be chosen to handle it. In the case of a request made using the {{{EventListener.html}EventListener}} annotation, the
builder used will <(not in all cases, if you specify async=false on your annotation the request will be a
normal http post)> be {{{../apidocs/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.html}DojoAjaxResponseBuilder}}.
Building on the example started in the {{{EventListener.html}EventListener}} overview, this is how you
would dynamically update the contents of a component:
+-----------------------------------------------------------------------
....
@EventListener(targets = "projectChoose", events = "onValueChanged")
public void projectSelected(IRequestCycle cycle)
{
cycle.getResponseBuilder().updateComponent("myComponentId");
}
....
+-----------------------------------------------------------------------
The string value passed in to <<>> is the component id of the component
which you would like to update.
Tapestry will correctly manage and render all javascript/form state/etc needed, depending on the component
type you are requesting an update on.
* Using ResponseBuilder for sending status messages and triggering client-side code
It is possible to trigger existing client-side code from a java listener method. This
is made possible by {{{../apidocs/org/apache/tapestry/services/ResponseBuilder.html}ResponseBuilder}}s
addStatusMessage method.
+-----------------------------------------------------------------------
....
@EventListener(targets = "projectChoose", events = "onValueChanged")
public void projectSelected(IRequestCycle cycle)
{
cycle.getResponseBuilder().updateComponent("myComponentId");
cycle.getResponseBuilder().addStatusMessage(null, "info", "A project was selected");
}
....
+-----------------------------------------------------------------------
When the client is sent the ajax response, tapestry's javascript will 'publish'
the status message at the specified topis, i.e. it will execute
dojo.event.topic.publish('info','A project was selected')
You can take advantage of this behavior in several different ways:
[[1]] <> - Dojo's Toaster is an example of a widget that
is subscribed to the 'info' topic. Whenever a message is published there, it'll
scroll itself into view and display it.
[[1]] <> - And making them behave like Toaster.
[[1]] <> - it's easy to triggger your code whenever
a message is published. Here's some javascript that will alert the message:
+-----------------------------------------------------------------------
dojo.event.topic.subscribe('info', function(msg) { alert(msg); });
+-----------------------------------------------------------------------