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
Sat Dec 21 14:52:19 UTC 2024
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
Sat Dec 21 14:52:19 UTC 2024
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 (see later examples).
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


<!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_4.xsd">
<body class="container">
    <h3>AJAX: What is Called and When</h3>
    
    <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 row">
    
        <div class="col-sm-9 col-sm-offset-1">
            <table class="table table-bordered">
                <tr>
                    <th>
                        In response to request from <strong>EventLink</strong> with Zone.<br/>
                        Eg. <t:eventlink event="updateTime1" async="true">Update the time</t:eventlink>
                        <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. <t:actionlink t:id="updateTime2" async="true">Update the time</t:actionlink>
                        <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">
                            <t:form t:id="formWithZone" async="true">
                                In response to request from <strong>Form</strong> with Zone.<br/>
                                Eg. Name: <t:textfield t:id="name1"/><t:submit value="Show"/><br/>
                                ${name1}&nbsp;
                            </t: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>
                        <t:form>
                            In response to value change in <strong>Select</strong> with Zone (see later examples).<br/>
                            Eg. <t:label for="carMake"/>:
                            <t:select t:id="carMake" model="carMakes" zone="carDisplayZone"
                                blankOption="ALWAYS" blankLabel="Choose..." validate="required"
                                secure="never"/>
                            <t:zone t:id="carDisplayZone" id="carDisplayZone">
                                ${carMake}&nbsp;
                            </t:zone>
                        </t: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>
                        <t:form>
                            In response to keyup in <strong>TextField</strong> mixing in <strong>ZoneUpdater</strong> with Zone (see later examples).<br/>
                            Eg. Name: <t:textfield t:id="name2" t:mixins="zoneUpdater" 
                                ZoneUpdater.clientEvent="keyup" ZoneUpdater.event="name2Changed" ZoneUpdater.zone="name2Zone"/><br/>
                            <t:zone t:id="name2Zone" id="name2Zone">
                                ${name2}&nbsp;
                            </t:zone>
                        </t: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>
    
            message: ${message}<br/><br/>
        </div>

    </div>
    
    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.4/apidocs/org/apache/tapestry5/corelib/components/ActionLink.html">ActionLink</a>, 
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/EventLink.html">EventLink</a>, 
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a>, 
    <a href="http://tapestry.apache.org/5.4/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.4/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.4/apidocs/org/apache/tapestry5/services/Request.html">Request</a>.<br/><br/>
    
    <t:pagelink page="Index">Home</t:pagelink><br/><br/>
    
    <t:tabgroup>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/ajax/AjaxWhatIsCalledAndWhen.tml"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/ajax/AjaxWhatIsCalledAndWhen.java"/>
        <t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/ajaxwhatiscalledandwhen.css"/>
    </t:tabgroup>
</body>
</html>


package jumpstart.web.pages.examples.ajax;

import java.util.Date;

import org.apache.tapestry5.annotations.Import;
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.apache.tapestry5.services.ajax.AjaxResponseRenderer;
import org.slf4j.Logger;

@Import(stylesheet={"css/examples/ajaxwhatiscalledandwhen.css"})
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;

    @Inject
    private AjaxResponseRenderer ajaxResponseRenderer;

    @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 onActivate() {
        logger.debug("...onActivate()");
    }

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

    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()");
    }

    void onUpdateTime1() {
        logger.debug("...onUpdateTime1()");
        if (request.isXHR()) {
            ajaxResponseRenderer.addRender(time1Zone);
        }
    }

    void onAction() {
        logger.debug("...onAction()");
        if (request.isXHR()) {
            ajaxResponseRenderer.addRender(time2Zone);
        }
    }

    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()");
    }

    void onSubmit() {
        logger.debug("...onSubmit()");
        if (request.isXHR()) {
            ajaxResponseRenderer.addRender(formZone);
        }
    }

    void onName2Changed() {
        logger.debug("...onName2Changed()");
        name2 = request.getParameter("param");
        if (name2 == null) {
            name2 = "";
        }
        if (request.isXHR()) {
            ajaxResponseRenderer.addRender(name2Zone);
        }
    }

    void onValueChangedFromCarMake(String carMake) {
        logger.debug("...onValueChangedFromCarMake()");
        this.carMake = carMake;
        carMakes = ALL_MAKES;
        if (request.isXHR()) {
            ajaxResponseRenderer.addRender(carDisplayZone);
        }
    }

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


.eg {
                margin: 20px 0;
}

table {
                background-color: rgb(244,248,250);
}

th {
                width: 300px;
                font-weight: normal;
}

td {
                width: 300px;
                font-weight: normal;
}

table>tbody>tr:last-child {
                border-bottom: 1px solid #dddddd;
}

#name {
                width: 40%;
}

.js-required {
                color: red;
                display: block;
                margin-bottom: 14px;
}

.js-recommended {
                color: red;
                display: block;
                margin-bottom: 14px;
}