    001// Copyright 2010, 2011 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.corelib.mixins;
    016
    017import org.apache.tapestry5.Block;
    018import org.apache.tapestry5.ComponentResources;
    019import org.apache.tapestry5.MarkupWriter;
    020import org.apache.tapestry5.annotations.AfterRender;
    021import org.apache.tapestry5.annotations.BeginRender;
    022import org.apache.tapestry5.annotations.Events;
    023import org.apache.tapestry5.annotations.MixinAfter;
    024import org.apache.tapestry5.ioc.annotations.Inject;
    025
    026/**
    027 * This mixin triggers <em>component event</em> notifications when the
    028 * attached component enters its {@link BeginRender} and {@link AfterRender}
    029 * render phases. A common use of this is to handle the "afterRender"
    030 * event to generate client-side JavaScript for content just rendered via a
    031 * {@link Block} (this is a common Ajax use case related to partial page
    032 * rendering). Since AJAX requests don't trigger afterRender or beforeRender
    033 * render phase events in the containing component or page, this mixin provides
    034 * a way of accessing those events as component events.
    035 * <p>
    036 * An example using the {@link org.apache.tapestry5.corelib.components.Any Any}
    037 * component within a zone:
    038 * <pre>
    039 * &lt;div t:type="Zone" id="myZone"&gt;
    040 *     &lt;t:any t:mixins="RenderNotification"&gt;
    041 *              &lt;!-- zone content -&gt;
    042 *      &lt;/div&gt;
    043 * &lt;/div&gt;
    044 * </pre>
    045 * The {@link MarkupWriter} is passed as the event context to your event handler
    046 * method(s), so your corresponding component or page class might look like:
    047 * <pre>
    048 * void onBeginRenderFromMyZone(MarkupWriter writer)
    049 * {
    050 *     writer.element("p");
    051 *     writer.write("before item render");
    052 *     writer.end();
    053 * }
    054
    055 * void onAfterRenderFromMyZone(MarkupWriter writer)
    056 * {
    057 *     writer.element("p");
    058 *     writer.write("after item render");
    059 *     writer.end();
    060 * }
    061 * </pre>
    062 * As an alternative, see the {@link org.apache.tapestry5.corelib.components.Trigger Trigger}
    063 * component, which does something similar but as a component rather than a mixin.
    064 *
    065 * @since 5.2.0
    066 * @tapestrydoc
    067 */
    068@Events(
    069{ "beginRender", "afterRender" })
    070@MixinAfter
    071public class RenderNotification
    072{
    073    @Inject
    074    private ComponentResources resources;
    075
    076    void beginRender(MarkupWriter writer)
    077    {
    078        trigger(writer, "beginRender");
    079    }
    080
    081    void afterRender(MarkupWriter writer)
    082    {
    083        trigger(writer, "afterRender");
    084    }
    085
    086    private void trigger(MarkupWriter writer, String eventName)
    087    {
    088        resources.triggerEvent(eventName, new Object[]
    089        { writer }, null);
    090    }
    091}