Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Clarified need for request.isXhr()
Div
stylefloat:right
titleRelated Articles
classaui-label
Content by Label
showLabelsfalse
showSpacefalse
titleRelated Articles
cqllabel in ("ajax","javascript") and space = currentSpace()

Tapestry provides easy-to-use support for Ajax, the technique of using JavaScript to dynamically update parts of a web page with content from the server without redrawing the whole page. With Tapestry, you can do simple Ajax updates without having to write any JavaScript code at all.

Div
stylefloat:right
titleRelated Articles
classaui-label
Content by Label
showLabelsfalse
showSpacefalse
titleRelated Articles
cqllabel in ("ajax","javascript") and space = currentSpace()

Ajax support Ajax support is included in many built-in components and component mixins via the async parameter (in Tapestry 5.4+) and the zone parameter (for earlier versions). Here we use an EventLink component to trigger an Ajax update of another area of the page:

...

Zones are Tapestry's approach to performing partial page updates. A Zone component renders as an HTML element, typically a <div>, and serves as a marker for where dynamically-updated content should be replaced. Starting in Tapestry 5.4 you can use any HTML element in your template as that marker, using the two-argument version of the addRender method.A zone A zone is recognizable in the DOM because it will have the attribute data-container-type=zone. The client-side support for Zones is keyed off of this attribute and value.

Starting in Tapestry 5.4 you can use any HTML element in your template as a zone marker, by passing its client-side id to the two-argument version of the addRender method.

A Zone updated can be triggered by an EventLink, ActionLink A Zone can be updated via an EventLink, ActionLink or Select component, or by a Form. All of these components support the async and/or zone parameters. Clicking such a link will invoke an event handler method on the server as normal ... except that a partial page response is sent to the client, and the content of that response is used to update the Zone's <div> in place.

...

Wiki Markup
{float:right|background=#eee|padding=0 1em}
    *JumpStart Demo:*
    [AJAX ActionLink|http://jumpstart.doublenegative.com.au/jumpstart/examples/ajax/actionlink]
{float}

Event Handler Return Types

In a traditional request, the return value of an event handler method may used to determine which page will render a complete response, and a redirect may sent to the client to render the new page (as a new request).

...

Note

Starting in Tapestry 5.3, Ajax event handlers typically have a void return type and use AjaxResponseRenderer to indicate which zone to update. The AjaxResponseRender approach means that the zone parameter's value (oridinarily indicating which zone to update) is no longer needed. Tapestry 5.4 introduced the async="true" parameter to avoid having to redundantly indicate which zone to update.

This return value is often just the zone's own body (as below), but it can also be an injected component or block. The value will be rendered, and that markup will be used on the client side to update the Zone's <div>.If you only have one zone to update and don't want to use AjaxResponseRenderer, you can instead return a value from your event handler method. The simplest case is just to rturn the zone's own body:

Code Block
languagejava
@Inject
private Request request;

@InjectComponent
private Zone myZone;
...
Object onActionFromSomeLink()
{
   return myZone.getBody(); // AJAX request, return zone's own body
} 

The possible return values are:

  • A An injected Block or Component to render as the response. The response will be a JSON hash, with a "content" key whose value is the rendered markup. This is the basis for updates with the Zone component.
  • The zone's own body (using Zone's getBody() method)
  • null (to redraw the current page)
  • A JSONObject or JSONArray, which will be sent as the response.
  • A StreamResponse, which will be sent as the response.
  • A Link, which will send a redirect to the client.
  • A page name (as a String), or a page class, or a page instance, which will send a redirect to the indicated page.

See Page Navigation for full descriptions of the above.

Graceful Degradation

Users who do not have JavaScript enabled may click EventLinks (or ActionLinks, or Forms) that are configured to update a Zone. When that occurs, the request will still be sent to the server, but Tapestry will handle it as a traditional request.

To support graceful degradation, you should detect that case in This happens automatically when your event handler method has a void return type.

However, to support graceful degradation when your event handler method has a non-void return type, you should detect non-Ajax requests and return a traditional response, typically null to redraw the whole page and return a traditional response: a page, page name or page class. This is accomplished by injecting the Request object, and invoking the isXHR() method. This value will be true for Ajax requests, and false for traditional request.

...

The renderer for each zone can be the zone itself, a block, a component, a Renderable or a RenderCommand ... or an object, such as String, that can be coerced to either of these.

@Inject private Form registrationForm; @Inject Block registrationHelp; Object onActionFromRegister() { return new MultiZoneUpdate("userInput", registrationForm).add("helpPanel",
       
registrationHelp
userInput).addRender("helpPanel", helpPanel);
}

    Note that MultiZoneUpdate is deprecated starting with Tapestry 5.3.

Section
Column
Code Block
languagejava
titleFor Tapestry 5.3 and later
@InjectComponent
private Zone userInput;

@InjectComponent
private Zone helpPanel;

@Inject
private AjaxResponseRenderer ajaxResponseRenderer;

void onActionFromRegister()
{
    ajaxResponseRenderer.addRender("userInput",
 
userInput).addRender("helpPanel", helpPanel); }
Column
Code Block
languagejava
titleFor Tapestry 5.1, 5.2 and 5.3

These examples assume This example assumes that there are two zones, "userInput" and "helpPanel", somewhere in the rendered page, waiting to receive the updated content.

...

However, to coordinate things on the client side, it is necessary for components that wish to update the zone know the client-side element id. This is specified with the id parameter of the Zone component. If the id parameter is not bound, then a unique value (for the current page and render) is generated by Tapestry and this value is difficult to predict. (The actual value will be available as the clientId property of the Zone component itself.)

Remember that the component id (t:id) is used to inject the Zone component into the containing page or component. The
client-side id (id) is used ... on the client side to orchestrate requests and updates. You will often seen the following construct:

Code Block
languagexml
<t:zone t:id="myZone" id="myzone"> ... </t:zone>

<t:actionlink t:id="update" zone="myzone">update</t:actionlink>

The Containing Zone (zone="^")

Since
since5.2
If the Form or Link is enclosed by the Zone itself, then the {{zone}} parameter may be set to the special value {{^}}. The carat is evaluated, on the client side, by searching up form the form or link element for the first enclosing element that is a Zone. In this way, the client-side coordination can occur without having to know what the specific client-side id of the Zone is. Because of this, in some cases, it is no longer necessary to specify the Zone's {{id}} parameter.

An Update div within a Zone div (Tapestry 5.3 and earlier)

Deprecated
_This feature is removed starting with Tapestry 5.4_

...

Deprecated
_This feature refers to client-side logic only present in Tapestry 5.3 or earlier. For 5.4, there are client-side events that are triggered before and after changes to the Zone; listeners on those events can trigger whatever animations they like.

...

A Zone may be initially visible or invisible. When a Zone is updated, it is made visible if not currently so. This is accomplished via a function on the Tapestry.ElementEffect client-side object. By default, the show() function is used for this purpose. If you want Tapestry to call a different Tapestry.ElementEffect function when updates occur, specify its name with the zone's show parameter.

...