5 Replies Latest reply on Aug 12, 2009 5:41 AM by antibrumm

    reRender and rendered issue or feature?

    antibrumm

      Hello all.
      I'm kinda new to Richfaces with using it since around 3 month and i ran into a problem now where i'm not getting what happens.

      I find it quite strange that the rendered attributes are evaluated even if the component is outside of the rerender regions. Is that normal behavior because of a diffrent phase in the jsf lifecycle or do i something wrong in my code?

      (The basis is a straight forward Seam application created with the Eclipse wizard)

      Simple Helper object

      @Name("testHelper")
      @Scope(ScopeType.PAGE)
      public class TestHelper implements Serializable {
      
       /**
       *
       */
       private static final long serialVersionUID = 1L;
      
       @Logger
       Log log;
      
       public void action(String action) {
       log.info("action " + action);
       }
      
       public String getText(String text) {
       log.info("getText: " + text);
       return text;
       }
      
      }
      


      I've created this page for a test.
       <ui:define name="body">
      
       <rich:panel id="panel1">
       <a:form>
       <h:outputText value="#{testHelper.getText('text1')}" />
       <br />
       <a:commandButton action="#{testHelper.action('button1')}"
       value="Action on Panel1" reRender="panel1" />
       <a:commandButton action="#{testHelper.action('button2')}"
       value="Action on Panel2" reRender="panel2" />
       </a:form>
       </rich:panel>
      
       <rich:panel id="panel2">
       <a:form>
       <h:outputText value="#{testHelper.getText('text2')}" />
       <br />
       <a:commandButton action="#{testHelper.action('button3')}"
       value="Action on Panel2" reRender="panel2" />
       <a:commandButton action="#{testHelper.action('button4')}"
       value="Action on Panel1" reRender="panel1" />
       </a:form>
       </rich:panel>
      
       </ui:define>
      


      As expected if i press "Action on Panel1" only the panel1 if rerendered and if get the output:
      15:21:17,518 INFO [TestHelper] action button1
      15:21:17,549 INFO [TestHelper] getText: text1

      Then i created another page with the rendered attribute on the outputtext:
       <ui:define name="body">
      
       <rich:panel id="panel1">
       <a:form>
       <h:outputText value="#{testHelper.getText('text1')}" rendered="#{testHelper.getText('testText') == 'testText'}" />
       <br />
       <a:commandButton action="#{testHelper.action('button1')}"
       value="Action on Panel1" reRender="panel1" />
       <a:commandButton action="#{testHelper.action('button2')}"
       value="Action on Panel2" reRender="panel2" />
       </a:form>
       </rich:panel>
      
       <rich:panel id="panel2">
       <a:form>
       <h:outputText value="#{testHelper.getText('text2')}" />
       <br />
       <a:commandButton action="#{testHelper.action('button3')}"
       value="Action on Panel2" reRender="panel2" />
       <a:commandButton action="#{testHelper.action('button4')}"
       value="Action on Panel1" reRender="panel1" />
       </a:form>
       </rich:panel>
      
       </ui:define>
      

      And here suddenly i get outputs from both rendered attributes with clicking on "Action on Panel1"...

      16:24:48,306 INFO [TestHelper] getText: testText1
      16:24:48,321 INFO [TestHelper] getText: testText1
      16:24:48,321 INFO [TestHelper] getText: testText1
      16:24:48,337 INFO [TestHelper] action button1
      16:24:48,353 INFO [TestHelper] getText: testText1
      16:24:48,353 INFO [TestHelper] getText: testText1
      16:24:48,353 INFO [TestHelper] getText: testText1
      16:24:48,368 INFO [TestHelper] getText: testText1
      16:24:48,368 INFO [TestHelper] getText: testText1
      16:24:48,368 INFO [TestHelper] getText: text1
      16:24:48,384 INFO [TestHelper] getText: testText2

      If someone could explain me why this happens would be perfect :)

      Greetings
      Anti

        • 1. Re: reRender and rendered issue or feature?
          antibrumm

          As stated by another "An editing function could be nice in this forum here." :)

          The last code should be this one. Sorry, a perfect start here :o)

           <ui:define name="body">
          
           <rich:panel id="panel1">
           <a:form>
           <h:outputText value="#{testHelper.getText('text1')}" rendered="#{testHelper.getText('testText1') == 'testText1'}" />
           <br />
           <a:commandButton action="#{testHelper.action('button1')}"
           value="Action on Panel1" reRender="panel1" />
           <a:commandButton action="#{testHelper.action('button2')}"
           value="Action on Panel2" reRender="panel2" />
           </a:form>
           </rich:panel>
          
           <rich:panel id="panel2">
           <a:form>
           <h:outputText value="#{testHelper.getText('text2')}" rendered="#{testHelper.getText('testText2') == 'testText2'}" />
           <br />
           <a:commandButton action="#{testHelper.action('button3')}"
           value="Action on Panel2" reRender="panel2" />
           <a:commandButton action="#{testHelper.action('button4')}"
           value="Action on Panel1" reRender="panel1" />
           </a:form>
           </rich:panel>
          
           </ui:define>
          


          • 2. Re: reRender and rendered issue or feature?
            alexsmirnov

            That is feature related to components that are "always updated" by ajax, for example <rich:message.. > are always included into ajax response because these components should display actual values.
            To tell framework that you have no such components on the page, use "limitToList='true'" attribute.
            Keep in mind what 'rendered attribute affects all JSF phases, including decode phase as well.

            • 3. Re: reRender and rendered issue or feature?
              antibrumm

              Thanks alex for your reply.
              I've tried it with the "limitToList='true'" attribute and i get the exact same result.
              I'm not sure if i completly understand what happens in the lifecycle.
              For me it looks like the complete page is rendered by JSF and Richfaces returns only the part that is interesting for the re-rendering. Is that correct?

              My real problem is that i have a dynamic search field where the user can add and remove filters for a query. The searchResult is displayed in a datatable with the entityquery in the back. I was going to hide the complete table if the resultcount is 0 to save some space in the layout. That works fine in a JSF approach.

              With RichFaces however i define the rerender for either the "searchfilter" ("add filter" button) or "searchresults" ("search" button). The rerendering looks fine. But since the rendered attribute is evaluated all the time we get some problems if the table is displayed with some results, the user changes the query and the data in the table changes but are not redrawn.

              It's not that we have no workaround for this but I need to find out why something outside of the rerender region we define is processed in the lifecycle.
              In this case it can be quite dangerous and not that obvious that some code is executed even if you didnt define it.

              It could also be that I am just missing something.

              • 4. Re: reRender and rendered issue or feature?
                ilya_shaikovsky

                As Alex said rendered attribute affects all JSF phases, including decode phase as well.
                So you should limit not only encoding but decoding as well using a4j:region component or ajaxSingle ajax components attribute.

                • 5. Re: reRender and rendered issue or feature?
                  antibrumm

                  Thanks Ilya.
                  Isn't the rich:panel already a a4j:region? I thought i've tried that approach also already. But will do it again.
                  Can you or anyone else get me a "running" version of this issue. It seems that you know what to do about it :)

                  Btw:
                  I've also tried to use the c:if instead of the rendered attribute. I was a little surprised that the outcome is not the same. With the if tag the testText1 and 2 are called only once and in the render phase only. We the rendered attribute i see alot more of access to this method in (and only) the render phase also.
                  I was thinking the rendered attribute should be kind of a shortcut to the if function.

                  Thanks
                  Anti