AJAX: What is Called and When

This page demonstrates what methods are called, and when, in various AJAX situations.

It provides, and logs, every page lifecycle method, several render phase methods, and every component event handler method.
This table shows what you will see in the logs if you configure log4j to record this page at debug level:
In response to request from EventLink with Zone.
Eg. Update the time
Tue Sep 02 21:32:39 EST 2014
pageAttached()
...onActivate()
...onUpdateTime1()
...Tapestry generates zone content...
...getTime1()
pageDetached()
Tapestry returns zone content
In response to request from ActionLink with Zone.
Eg. Update the time
Tue Sep 02 21:32:39 EST 2014
pageAttached()
...onActivate()
...onAction()
...Tapestry generates zone content...
...getTime2()
pageDetached()
Tapestry returns zone content
In response to request from Form with Zone.
Eg. Name:
 
pageAttached()
...onActivate()
...onPrepareForSubmit()
...onPrepare()
...onValidateFromName1()
...setName1()
...onSelected()
...onValidateFromFormWithZone()
...onSuccess()
...onSubmit()
...Tapestry generates zone content...
...onPassivate()
...onPrepareForRender()
...onPrepare()
...getName1()
...getName1() [sic]
pageDetached()
Tapestry returns zone content
In response to value change in Select with Zone.
Eg. :
 
pageAttached()
...onActivate()
...onValueChangedFromCarMake()
...Tapestry generates zone content...
...setCarMake()
...getCarMake()
pageDetached()
Tapestry returns zone content
In response to keyup in TextField mixing in ZoneUpdater with Zone (see later examples).
Eg. Name:
 
pageAttached()
...onActivate()
...onName2Changed()
...Tapestry generates zone content...
...getName2()
pageDetached()
Tapestry returns zone content
Message: This message is generated by getMessage().

References: Page Lifecycle, Component Rendering, ActionLink, EventLink, Form, Submit, Inge's Zone Updater, Ajax and Zones, Zone, Logging, Request.

Home

AjaxWhatIsCalledAndWhen.tml


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like &nbsp; 
     We use a "strict" DTD to make IE follow the alignment rules. -->
     
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
<head>
    <link rel="stylesheet" type="text/css" href="${context:css/examples/js.css}"/>
    <style type="text/css">
        .eg     { border: none; margin: 0; color: #333; }
        tr      { background-color: rgb(204, 190, 153); border: black 2px outset; padding: 2px; font-family: 'Trebuchet MS'; }
        th      { width:300px; text-align:left; font-weight: normal; padding: 0.4em; }
        td      { width:300px; text-align:left; font-weight: normal; padding: 0.4em; vertical-align: top;}
        .t-zone { background-color: rgb(204, 190, 153); }
    </style>
</head>
<body>
    <h1>AJAX: What is Called and When</h1>
    
    <noscript class="js-required">
        ${message:javascript_required}
    </noscript>     

    This page demonstrates what methods are called, and when, in various AJAX situations.<br/><br/>
    
    It provides, and logs, every page lifecycle method, several render phase methods, and every component event handler method.<br/> 
    This table shows what you will see in the logs if you configure log4j to record this page at debug level:
    
    <div class="eg">
        <table style="border:thin gray 2px;">
            <tr>
                <th>
                    In response to request from <strong>EventLink</strong> with Zone.<br/>
                    Eg. <a t:type="EventLink" t:event="updateTime1" t:zone="time1Zone" href="#">Update the time</a>
                    <t:zone t:id="time1Zone" id="time1Zone">
                        ${time1}
                    </t:zone>
                </th>
                <td>
                    pageAttached()<br/>
                    ...onActivate()<br/>
                    ...onUpdateTime1()<br/>
                    <em>...Tapestry generates zone content...</em><br/>
                    ...getTime1()<br/>
                    pageDetached()<br/>
                    <em>Tapestry returns zone content</em><br/>
                </td>
            </tr>
            <tr>
                <th>
                    In response to request from <strong>ActionLink</strong> with Zone.<br/>
                    Eg. <a t:type="ActionLink" t:id="updateTime2" t:zone="time2Zone" href="#">Update the time</a>
                    <t:zone t:id="time2Zone" id="time2Zone">
                        ${time2}
                    </t:zone>
                </th>
                <td>
                    pageAttached()<br/>
                    ...onActivate()<br/>
                    ...onAction()<br/>
                    <em>...Tapestry generates zone content...</em><br/>
                    ...getTime2()<br/>
                    pageDetached()<br/>
                    <em>Tapestry returns zone content</em><br/>
                </td>
            </tr>
            <tr>
                <th>
                    <t:zone t:id="formZone" id="formZone">
                        <form t:type="form" t:id="formWithZone" t:zone="^">
                            In response to request from <strong>Form</strong> with Zone.<br/>
                            Eg. Name: <input t:type="TextField" t:id="name1"/><input t:type="Submit" value="Show"/><br/>
                            ${name1}&nbsp;
                        </form>
                    </t:zone>
                </th>
                <td>
                    pageAttached()<br/>
                    ...onActivate()<br/>
                    ...onPrepareForSubmit()<br/>
                    ...onPrepare()<br/>
                    ...onValidateFromName1()<br/>
                    ...setName1()<br/>
                    ...onSelected()<br/>
                    ...onValidateFromFormWithZone()<br/>
                    ...onSuccess()<br/>
                    ...onSubmit()<br/>
                    <em>...Tapestry generates zone content...</em><br/>
                    ...onPassivate()<br/>
                    ...onPrepareForRender()<br/>
                    ...onPrepare()<br/>
                    ...getName1()<br/>
                    ...getName1() <em>[sic]</em><br/>
                    pageDetached()<br/>
                    <em>Tapestry returns zone content</em><br/>
                </td>
            </tr>
            <tr>
                <th>
                    <form t:type="form">
                        In response to value change in <strong>Select</strong> with Zone.<br/>
                        Eg. <t:label for="carMake"/>:
                        <select t:type="select" t:id="carMake" t:model="carMakes" t:zone="carDisplayZone"
                            t:blankOption="ALWAYS" t:blankLabel="Choose..." t:validate="required"/>
                        <t:zone t:id="carDisplayZone" id="carDisplayZone">
                            ${carMake}&nbsp;
                        </t:zone>
                    </form>
                </th>
                <td>
                    pageAttached()<br/>
                    ...onActivate()<br/>
                    ...onValueChangedFromCarMake()<br/>
                    <em>...Tapestry generates zone content...</em><br/>
                    ...setCarMake()<br/>
                    ...getCarMake()<br/>
                    pageDetached()<br/>
                    <em>Tapestry returns zone content</em><br/>
                </td>
            </tr>
            <tr>
                <th>
                    <form t:type="form">
                        In response to keyup in <strong>TextField</strong> mixing in <strong>ZoneUpdater</strong> with Zone (see later examples).<br/>
                        Eg. Name: <input t:type="TextField" t:id="name2" t:mixins="zoneUpdater" t:clientEvent="keyup" t:event="name2Changed" t:zone="name2Zone"/><br/>
                        <t:zone t:id="name2Zone" id="name2Zone">
                            ${name2}&nbsp;
                        </t:zone>
                    </form>
                </th>
                <td>
                    pageAttached()<br/>
                    ...onActivate()<br/>
                    ...onName2Changed()<br/>
                    <em>...Tapestry generates zone content...</em><br/>
                    ...getName2()<br/>
                    pageDetached()<br/>
                    <em>Tapestry returns zone content</em><br/>
                </td>
            </tr>
        </table>
    </div>
    
    Message: ${message}<br/><br/>
    
    References: 
    <a href="http://tapestry.apache.org/page-life-cycle.html">Page Lifecycle</a>, 
    <a href="http://tapestry.apache.org/component-rendering.html">Component Rendering</a>, 
    <a href="http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/ActionLink.html">ActionLink</a>, 
    <a href="http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/EventLink.html">EventLink</a>, 
    <a href="http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a>, 
    <a href="http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/Submit.html">Submit</a>, 
    <a href="http://tinybits.blogspot.com/2010/03/new-and-better-zoneupdater.html">Inge's Zone Updater</a>,
    <a href="http://tapestry.apache.org/ajax-and-zones.html">Ajax and Zones</a>, 
    <a href="http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/corelib/components/Zone.html">Zone</a>, 
    <a href="http://tapestry.apache.org/logging.html">Logging</a>, 
    <a href="http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/services/Request.html">Request</a>.<br/><br/>
    
    <a t:type="pagelink" t:page="Index" href="#">Home</a><br/><br/>
    
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/pages/examples/ajax/AjaxWhatIsCalledAndWhen.tml"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/pages/examples/ajax/AjaxWhatIsCalledAndWhen.java"/>
    <t:sourcecodedisplay src="/web/src/main/java/jumpstart/web/css/examples/js.css"/>
</body>
</html>

AjaxWhatIsCalledAndWhen.java


package jumpstart.web.pages.examples.ajax;

import java.util.Date;

import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.Request;
import org.slf4j.Logger;

public class AjaxWhatIsCalledAndWhen {
    static final private String[] ALL_MAKES = new String[] { "Honda", "Toyota" };
    
    // Screen fields

    private String name1;

    private String name2;

    private String carMake;

    @Property
    private String[] carMakes;

    // Generally useful bits and pieces

    @Inject
    private Logger logger;

    @Inject
    private Request request;

    @InjectComponent
    private Zone time1Zone;

    @InjectComponent
    private Zone time2Zone;

    @InjectComponent
    private Zone formZone;

    @InjectComponent
    private Zone name2Zone;

    @InjectComponent
    private Zone carDisplayZone;

    // The code

    void pageLoaded() {
        logger.debug("   ");
        logger.debug("pageLoaded()");
    }

    void pageAttached() {
        logger.debug("   ");
        logger.debug("pageAttached()");
    }

    void pageDetached() {
        logger.debug("pageDetached()");
    }

    void onPassivate() {
        logger.debug("...onPassivate()");
    }

    void onActivate() {
        logger.debug("...onActivate()");
    }

    void setupRender() {
        logger.debug("...setupRender()");
        if (carMakes == null) {
            carMakes = ALL_MAKES;
        }
    }

    void beginRender() {
        logger.debug("...beginRender()");
    }

    void afterRender() {
        logger.debug("...afterRender()");
    }

    void cleanupRender() {
        logger.debug("...cleanupRender()");
    }

    Object onUpdateTime1() {
        logger.debug("...onUpdateTime1()");
        return request.isXHR() ? time1Zone.getBody() : null;
    }

    Object onAction() {
        logger.debug("...onAction()");
        return request.isXHR() ? time2Zone.getBody() : null;
    }

    void onPrepareForRender() {
        logger.debug("...onPrepareForRender()");
    }

    void onPrepare() {
        logger.debug("...onPrepare()");
    }

    void onPrepareForSubmit() {
        logger.debug("...onPrepareForSubmit()");
    }

    void onValidateFromName1() {
        logger.debug("...onValidateFromName1()");
    }

    void onSelected() {
        logger.debug("...onSelected()");
    }

    void onValidateFromFormWithZone() {
        logger.debug("...onValidateFromFormWithZone()");
    }

    void onSuccess() {
        logger.debug("...onSuccess()");
    }

    void onFailure() {
        logger.debug("...onFailure()");
    }

    Object onSubmit() {
        logger.debug("...onSubmit()");
        return request.isXHR() ? formZone.getBody() : null;
    }

    Object onName2Changed() {
        logger.debug("...onName2Changed()");
        name2 = request.getParameter("param");
        if (name2 == null) {
            name2 = "";
        }
        return request.isXHR() ? name2Zone.getBody() : null;
    }

    Object onValueChangedFromCarMake(String carMake) {
        logger.debug("...onValueChangedFromCarMake()");
        this.carMake = carMake;
        carMakes = ALL_MAKES;
        return carDisplayZone.getBody();
    }

    public String getMessage() {
        logger.debug("...getMessage()");
        return "This message is generated by getMessage().";
    }

    public Date getTime1() {
        logger.debug("...getTime1()");
        return new Date();
    }

    public Date getTime2() {
        logger.debug("...getTime2()");
        return new Date();
    }

    public String getName1() {
        logger.debug("...getName1()");
        return name1;
    }

    public void setName1(String name1) {
        logger.debug("...setName1()");
        this.name1 = name1;
    }

    public String getCarMake() {
        logger.debug("...getCarMake()");
        return carMake;
    }

    public void setCarMake(String carMake) {
        logger.debug("...setCarMake()");
        this.carMake = carMake;
    }
    
    public String getName2() {
        logger.debug("...getName2()");
        return name2;
    }
    
    public void setName2(String name2) {
        logger.debug("...setName2()");
        this.name2 = name2;
    }
}

js.css


body            { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; color: #333;
                    line-height: 17px; }
h1              { font-size: 26px; line-height: 20px; } /* For IE 7 */
form            { margin: 0; }

.eg             { margin: 20px 0; padding: 20px; color: #888; 
                    border: 1px solid #ddd; border-radius: 4px; -webkit-border-radius: 4px; -mox-border-radius: 4px; }

a               { text-decoration: none; color: #3D69B6; }
a:hover         { text-decoration: underline; }

/* For javascript examples. */
.js-required    { color: red; display: block; margin-bottom: 14px; }
.js-recommended { color: red; display: block; margin-bottom: 14px; }

.grid           { border-collapse: collapse; border-spacing: 0; border: 1px solid #dddddd; font-size: 13px; }
.grid tr.odd        { background-color: #f8f8f8; }
.grid tr:hover      { background-color: #eeeeee; }
.grid th        { padding: 3px 5px; text-align: left; width: 130px; border: 1px solid #dddddd; 
                    font-weight: normal; background-color: #eeeeee; 
                    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbfbfb', endColorstr='#e4e4e4'); /* for IE */
                    background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#e4e4e4)); /* for webkit browsers */
                    background: -moz-linear-gradient(top, #fbfbfb, #e4e4e4); /* for firefox 3.6+ */ }
.grid td        { padding: 3px 5px; text-align:left; }