webtier@glassfish.java.net

Re: Custom Renderer Doesn't Render Children on AJAX Postback

From: <webtier_at_javadesktop.org>
Date: Tue, 25 May 2010 07:29:36 PDT

I have solved my own problem.

When you implement your own custom renderer and try to update the component within the component tree through AJAX, you must implement a Phase Listener in tandem to update the client ID of the component at the RENDER RESPONSE phase.

You can achieve a partial page update by visiting the phase client IDs through the visitTree method accessible through the FacesContext viewRoot. When calling the visitTree method you will need to set up an inner class VisitCallback to access each component associated with it's client id.

Here is an example: (Feel free to interject any code review comments)

public class TestPhaseListener implements PhaseListener {
   @Override
   public void afterPhase(PhaseEvent event) { }

   @Override
   public void beforePhase(PhaseEvent event) {
      FacesContext context = FacesContext.getCurrentInstance();
      ExternalContext extContext = context.getExternalContext();

      if (context.getPartialViewContext.isAjaxRequest()) {
         try {
            List<String> phaseClientIds = (List<String>) context.getPartialViewContext.getRenderIds();
            EnumSet<VisitHint> hints = EnumSet.of(VisitHint.SKIP_UNRENDERED);
            PartialVisitContext visitContext = (PartialVisitContext) VisitContext.createVisitContext(context, phaseClientIds, hints);
            
            extContext.setResponseContentType("text/xml");
            extContext.addResponseHeader("Cache-Control", "no-cache");

            PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
            writer.startDocument();

            context.getViewRoot().visitTree(visitContext, RENDER_RESPONSE);

            writer.endDocument();
            writer.flush();
            context.responseComplete();
         } catch (Exception e) {
            e.printStackTrace();
         }
      }
   }

   @Override
   public PhaseId getPhaseId() {
      return PhaseId.RENDER_RESPONSE;
   }

   public static final VisitCallback RENDER_RESPONSE = new VisitCallback() {
      public VisitResult visit(VisitContext visitContext, UIComponent component) {
         FacesContext facesContext = visitContext.getFacesContext();
         PartialResponseWriter writer = facesContext.getPartialViewContext().getPartialResponseWriter();
         MyComponent myComponent = null;

         ValueExpression ve = component.getParent().getValueExpression("myComponent");
         if (ve != null) {
            myComponent = (MyComponent) ve.getValue(facesContext.getELContext());
         }

         try {
            writer.startUpdate(component.getClientId());
                   
            if (myComponent != null) {
               UIComponent compositeComponent = myComponent.getCompositeComponent();
 
               if (compositeComponent != null) {
                  component.getParent().getChildren().add(compositeComponent);
                  compositeComponent.encodeAll(facesContext);
               }
            }

            writer.endUpdate();
         } catch (Exception e) {
            e.printStackTrace();
         }

         return VisitResult.REJECT;
      }
   }
}
[Message sent by forum member 'dperriero']

http://forums.java.net/jive/thread.jspa?messageID=471356