Indeed you could handle all bubbled up events in the page class.

Sometimes I prefer to keep page classes clear of event handling and just focus them on handling requests and providing the content - this to me is better SoC. So I capture the bubbled up events in a single top-level child component of the page. This component then triggers ajaxResponseRenderer.addRender(zone)... for any zones that contain subordinate components to refresh.

This approach produces some nice clean code. see below

John


In this example most the pages components need to be refreshed on login, so it might just be better to rerender the whole page anyway, but this solution does allow for more granularity if required.

page template
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";
     xmlns:p="tapestry:parameter">
   <head t:type="if" t:test="style">
       <style type="text/css">
           <t:outputraw value="style"/>
       </style>
   </head>
   <body>
       <div class="embwizard">
           <t:if t:test="showWizard">
               <t:wizard vendorIdParm="vendorId"/>
               <p:else>
                   <p>
                       ${message:text.unknownvendor}
                   </p>
               </p:else>
           </t:if>
           <p style="text-align:center;">${message:sitename}</p>
       </div>
   </body>
</html>

page class
@Property
@Persist(PersistenceConstants.FLASH)
private String vendorUsername;
@Property
@Persist(PersistenceConstants.CLIENT)
private Integer vendorId;
@Property
private String style;
@Property
private boolean showWizard;
@Inject
private VendorDAO vendorDAO;
@Inject
PageRenderLinkSource linkSource;
@Inject
private Logger log;
@SessionState(create = true)
private SessionStateBean stateBean;

 void onActivate(String param) {
       // make this page a home page
Link homePage = linkSource.createPageRenderLinkWithContext(EmbWizard.class, param);
       stateBean.setHomePage(homePage);
       if (param != null) {
           try {
               Vendor vendor = vendorDAO.getVendorByUsername(param, true);
                   // vendor handling logic...
                   } else {
                       log.warn("vendor not available " + param);
                   }
               } else {
                   log.warn("vendor not found " + param);
               }
           } catch (DAOException ex) {
               log.error("activate error", ex);
           }
       }
   }

   private boolean assignGuest() {
       // start new quest session?
       if (!stateBean.isActive()) {
           stateBean.setUser(UserBeanFactory.nextGuest());
           return true;
       }
       return false;
   }

   Object[] onPassivate() {
       return new String[]{vendorUsername};
   }
}

Wizard.tml - the top level child component of page
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd";
     xmlns:p="tapestry:parameter"  xmlns:tx="tapestry-library:tapx">
   <div class="wizard">
       <t:zone t:id="wizardZone" id="wizardZone">
           <t:if test="showDiary">
<t:venueworkchooser vendorIdParm="vendorIdParm" venueIdParm="venueId" bookableParm="showDiary" workIdParm="workId"/>
               <t:zone t:id="wizDiaryZone" id="wizDiaryZone">
<t:easydiary workIdParm="workId" vendorIdParm="vendorIdParm" venueIdParm="venueId"/>
               </t:zone>
               <t:zone t:id="bookingsZone" id="bookingsZone">
                   <t:if test="showBookings">
<t:bookings t:id="bookingsComponent" vendorIdParm="vendorIdParm"/>
                   </t:if>
               </t:zone>
<t:controlpanel vendorIdParm="vendorIdParm"/> [this contains an ajax login form that fires onLoginComplete]
           </t:if>
           <t:if test="showContactDetails">
<t:contactDetails t:id="contactDetails" vendorIdParm="vendorIdParm"/>
           </t:if>
       </t:zone>
   </div>
</html>

Wizard.java - mainly handling events and  not much else
...
public Integer getVendorIdParm() {
   return vendorIdParm;
}

@SetupRender
void setup() {
   try {
       Vendor vendor = vendorDAO.getVendor(vendorIdParm);
       venueId = vendor.getVenueList().get(0).getIdVenue();
       showDiary = true;
       showContactDetails = false;
   } catch (DAOException ex) {
       log.error("setup error", ex);
   }
}

public boolean isAuthenticated() {
   if (stateBean != null) {
       return stateBean.isActive(UserType.CLIENT);
   } else {
       return false;
   }
}

public boolean onLoginComplete(Object[] contextValues) {
   try {
       log.debug("onLoginComplete "
               + Arrays.asList(contextValues));
       showBookings = true;
       ajaxResponseRenderer.addRender(bookingsZone);
   } catch (Exception ex) {

   }
   return true;
}

public boolean onChangedVenue(Object[] contextValues) {
   try {
       log.debug("onVenueChanged "
               + Arrays.asList(contextValues));
       venueId = (Integer) contextValues[0];
       ajaxResponseRenderer.addRender(wizardZone);
   } catch (Exception ex) {
       ex.printStackTrace();
   }
   return true;
}

public boolean onWorkSelected(Object[] contextValues) {
   try {
       log.debug("onWorkSelected "
               + Arrays.asList(contextValues));
       workId = (Integer) contextValues[0];
       ajaxResponseRenderer.addRender(wizDiaryZone);
   } catch (Exception ex) {
       ex.printStackTrace();
   }
   return true;
}

public boolean onGuestBookingComplete(Object[] contextValues) throws
       IllegalSessionStateException {
   log.debug("onGuestBookingComplete "
           + Arrays.asList(contextValues));
   Reservation reservation = (Reservation) contextValues[0];
   if (reservation != null) {
       contactDetails.setReservation(reservation);
       showDiary = false;
       showContactDetails = true;
       ajaxResponseRenderer.addRender(wizardZone);
   }
   return true;
}

public boolean onScheduleCallComplete(Object[] contextValues) throws
       IllegalSessionStateException {
   log.debug("onScheduleCallComplete "
           + Arrays.asList(contextValues));
   showBookings = true;
   ajaxResponseRenderer.addRender(bookingsZone);
   return true;
}

public boolean onContactDetailsCancelled(Object[] contextValues) {
log.debug("onContactDetailsCancelled " + java.util.Arrays.asList(contextValues));
   setup();
   ajaxResponseRenderer.addRender(wizardZone);
   return true;
}

public void onContactDetailsComplete(Object[] contextValues) {
log.debug("onContactDetailsComplete " + java.util.Arrays.asList(contextValues));
   Integer clientId = (Integer) contextValues[0];
   ajaxResponseRenderer.addRender(wizardZone);
}


-----Original Message----- From: Lance Java
Sent: Tuesday, October 14, 2014 5:47 PM
To: Tapestry users
Subject: Re: How do I render zone from component A in component B

I think you might be having the same issue I had a while ago [1]

Both the layout and the component are defined by the page. It's a bit
counter intuitive but the layout is not the component's parent so events
will not bubble up to it. The page is the parent to both.

[1]
http://apache-tapestry-mailing-list-archives.1045711.n5.nabble.com/Event-Bubbling-not-working-td5722372.html

---
This email is free from viruses and malware because avast! Antivirus protection 
is active.
http://www.avast.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to