Event Bubbling

If a component's event handler method returns true, the handling of that event is aborted. Otherwise, the event "bubbles up".

"Bubbling up" means that if there are no more matching event handlers in the component (see the Multiple Method Matches example) then the component will trigger the same event in its containing component. The containing component in this example is the page.

Here we have 4 instances of MyComponent. MyComponent renders an EventLink with the event name we give. We give 4 event names: EventA, EventB, EventC, and EventD.

Server-side, MyComponent handles 3 events: EventA, EventB, and EventC; and the page handles 6 events: EventA, EventB, EventC, EventD, EventE, and EventX.
EventD bubbled up to the page.

EventA
EventB
EventC
EventD
References: Event Bubbling, ComponentResources.

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>Event Bubbling</h3>
    If a component's event handler method returns <em>true</em>, the handling of that event is aborted. Otherwise, the event "bubbles up".<br/><br/>

    "Bubbling up" means that if there are no more matching event handlers in the component (see the Multiple Method Matches example) 
    then the component will trigger the same event in its containing component. The containing component in this example is the page.<br/><br/>

    Here we have 4 instances of MyComponent. MyComponent renders an EventLink with the event name we give. We give 4 event names: EventA, EventB, EventC, and EventD.<br/><br/>
    Server-side, MyComponent handles 3 events: EventA, EventB, and EventC; and the page handles 6 events: EventA, EventB, EventC, EventD, EventE, and EventX.<br/>

    <div class="eg">
        <t:if t:test="pageMessage">
            <span style="color:red;">${pageMessage}<br/><br/></span>
        </t:if>

        <t:examples.component.mycomponent eventname="EventA">EventA</t:examples.component.mycomponent><br/>
        <t:examples.component.mycomponent eventname="EventB">EventB</t:examples.component.mycomponent><br/>
        <t:examples.component.mycomponent eventname="EventC">EventC</t:examples.component.mycomponent><br/>
        <t:examples.component.mycomponent eventname="EventD">EventD</t:examples.component.mycomponent><br/>
    </div>
    
    References: 
    <a href="http://tapestry.apache.org/component-events.html#ComponentEvents-EventBubbling">Event Bubbling</a>, 
    <a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/ComponentResources.html">ComponentResources</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/component/EventBubbling.tml"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/component/EventBubbling.java"/>
        <t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/plain.css"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/components/examples/component/MyComponent.tml"/>
        <t:sourcecodetab src="/web/src/main/java/jumpstart/web/components/examples/component/MyComponent.java"/>
    </t:tabgroup>
</body>
</html>


package jumpstart.web.pages.examples.component;

import org.apache.tapestry5.PersistenceConstants;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;

@Import(stylesheet = "css/examples/plain.css")
public class EventBubbling {

    // Screen fields

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String pageMessage;

    // The code

    void onEventA() {
        pageMessage = "EventA bubbled up to the page.";
    }

    void onEventB() {
        throw new IllegalStateException("Cannot happen because MyComponent aborts handling of EventB.");
    }

    void onEventC() {
        throw new IllegalStateException("Cannot happen because MyComponent aborts handling of EventC.");
    }

    void onEventD() {
        pageMessage = "EventD bubbled up to the page.";
    }

    void onEventE() {
        throw new IllegalStateException("Cannot happen because there is no EventE.");
    }

    void onEventX() {
        pageMessage = "EventX bubbled up to the page.";
    }
}


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


<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<t:content>
    <t:eventlink event="prop:eventname"><t:body/></t:eventlink>
    <span style="color:red">${message}</span>
</t:content>
</html>


package jumpstart.web.components.examples.component;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.PersistenceConstants;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;

/**
 * MyComponent contains an EventLink and a message that is set up by whichever event handler method is triggered.
 */
public class MyComponent {

    // Parameters
    
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    @Property
    private String eventName; 
    
    // Screen fields

    @Property
    @Persist(PersistenceConstants.FLASH)
    private String message;

    // Generally useful bits and pieces

    @Inject
    private ComponentResources componentResources;

    // The code

    boolean onEventA() {
        message = "MyComponent handles EventA then bubbles it up.";
        
        // Let EventA bubble up.
        return false;
    }

    boolean onEventB() {
        message = "MyComponent handles EventB then aborts its handling.";
        
        // Abort handling of EventB.
        return true;
    }

    boolean onEventC() {
        message = "MyComponent handles EventC and triggers EventX in its place.";

        // Trigger the event "eventX" on myself which will then bubble up.
        componentResources.triggerEvent("eventX", null, null);

        // Abort handling of EventC.
        return true;
    }
    
    // We deliberately don't handle EventD, so it will bubble straight up.

}