------ 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); }); +-----------------------------------------------------------------------