9 Replies Latest reply on Apr 28, 2008 1:54 PM by jgreene

    How to automatically rerender custom JSF component on ajax s

    jgreene

      Hello -
      I'm using Richfaces, and I've created a custom JSF component that I want to be rerendered on any ajax submission. I looked at the functional spec for the UIRichMessages component, and this is one of its functional requirements, too, so I've tried to use the UIRichMessages component as a model by implementing AjaxOutput. However, I am not getting my component to rerender automatically on subsequent ajax submissions. Can someone let me know what else I need to do in my component, renderer, or configuration in order to accomplish this? I'm obviously doing something wrong. Thank you for any help.

        • 1. Re: How to automatically rerender custom JSF component on aj

          The regular way for re-rendering JSF component (custom or a statndard one) is mentioning it in the reRender attribute explicitly. What is a special with your component you want to re-render it during each Ajax request/response?

          • 2. Re: How to automatically rerender custom JSF component on aj
            jgreene

            Hi Sergey - Thanks for the response.
            This component is to be used on our main page and is intended to display messages with built-in rich effects - we did this partly to learn but mostly so we could display different types of messages the way we want. It is our own special message component. So whenever an ajax action happens, we want this component to rerender automatically, just like you have specified in the funtional requirements of the UIRichMessages component.

            • 3. Re: How to automatically rerender custom JSF component on aj
              nbelaevski

              Hello,

              It as simple as implementing org.ajax4jsf.component.AjaxOutput. The implementation should return true for ajaxRendered property when it's needed to be re-rendered, e.g. always:

              ...
              public class UIOutput implements AjaxOutput {
              
               ...
              
               public boolean isAjaxRendered() {
               return true;
               }
              
              
               public void setAjaxRendered(boolean value) {
               if (!value) throw new IllegalArgumentException("ajxRendered is read only");
               }
              }


              • 4. Re: How to automatically rerender custom JSF component on aj

                BTW, rich:messages is similar to:

                <a4j:outputPanel ajaxRendered="true">
                 <h:messages />
                </a4j:outputPanel>


                So, you can put a4j:outputPanel ajaxRendered="true" around your component or a composition that include your component to have an implicit auto update.
                Does it work for you or you need exactly like in rich:messages ?

                If you implement a specific interface,
                1) your component will be depended of RichFaces library
                2) it does not help to provide the auto-update for compositions

                • 5. Re: How to automatically rerender custom JSF component on aj
                  jgreene

                  Thank you, Nick -
                  This is exactly what I did, but it still didn't work. Perhaps I have something wrong on my xhtml page. I do not think the tag is within a form. Could that be the problem? Unless I have forgotten something simple, I cannot see what is wrong.


                  Sergey -
                  Thanks again for the response. We would really prefer that it behave just like the rich:messages so it would not need the a4j:outputPanel.

                  • 6. Re: How to automatically rerender custom JSF component on aj
                    nbelaevski

                    Do you see that encodeBegin/enodeEnd methods of your component are called for AJAX requests initiated by another components?

                    • 7. Re: How to automatically rerender custom JSF component on aj
                      jgreene

                      Hi Nick -
                      I have tested that before, and am testing it again, but I believe the only time the encodeBegin method executes is if I do what Sergey suggested by wrapping my tag with a4j:outputPanel and setting ajaxRendered="true". I am looking again right now and will get back to you again.

                      • 8. Re: How to automatically rerender custom JSF component on aj
                        jgreene

                        Nick -
                        I've done some testing, and made some adjustments, but my custom component is not being updated in the DOM, although it appears to be updated in the component tree on the server. Here is what I've done and what I've found.

                        My custom component is working for the most part now, even without a wrapping a4j:outputPanel component. I am using it with the a4j:status component, and using its "onstop" attribute to call a javascript function that fires the popup message functionality. We also have a phase listener that we wrote so that our messages queue would be cleared at the beginning of each ajax call - that seems to be working properly, too.

                        So the idea is that for each ajax call, our phase listener clears our message queue, and when an ajax call returns, if our custom component is rerendered properly on each ajax call, any new messages in the queue will be displayed as a temporary popup that fades after a few seconds (configurable). If the call results in no new messages being added, the "encodeBegin" method simply writes an empty string. My thinking is that the component's markup should be updated with this empty string - therefore no new messages to show when the javascript is called. However, what I'm seeing is that the encode method executes just fine on the server with each ajax call, and the phase listener is clearing our message queue before the "Apply Request Values" phase, but the popup message functionality still executes, indicating to me that the messages component is not being updated in the DOM. In fact, if I then view the browser source, the full markup for the message(s) is there, but if I then refresh the browser, the message(s) markup is gone, indicating that the component was updated on the server, but not in the DOM.

                        My component implements AjaxOutput as you suggested, but I also had to implement "setKeepTransient" and "isKeepTransient" in order to be able to compile. Could this be the problem? Here's this code snippet of how I implemented AjaxOutput:

                         // Implement AjaxOutput
                         public boolean isAjaxRendered()
                         {
                         return true;
                         }
                        
                         // Implement AjaxOutput
                         public void setAjaxRendered(boolean ajaxRendered)
                         {
                         if(!ajaxRendered)
                         new IllegalArgumentException();
                         }
                        
                         // Implement AjaxOutput
                         public boolean isKeepTransient()
                         {
                         return true;
                         }
                        
                         // Implement AjaxOutput
                         public void setKeepTransient(boolean ajaxRendered)
                         {
                         if(!ajaxRendered)
                         new IllegalArgumentException();
                         }
                        


                        I don't understand the other two methods that I needed to implement. The UIRichMessages don't implement them, but I couldn't build my project without them. The docs I found have the same notes as the "setAjaxRendered" and "isAjaxRendered", so I'm not sure. Thanks for any new help, Nick. I thought I had done everything correctly, but obviously not.

                        • 9. Re: How to automatically rerender custom JSF component on aj
                          jgreene

                          Nick -
                          I find that if I wrap my custom component in an a4j:outputPanel component with ajaxRendered="true", everything seems to work fine. So there seems to be some piece of information that I'm missing. I've implemented AjaxOutput, so I shouldn't have to wrap my component. The UIRichMessages examples I've seen do not wrap the UIRichMessages component, either.

                          Any help would be appreciated. Thank you.