9 Replies Latest reply on May 2, 2008 9:15 AM by shandor

    reRender a component with rendered=

    shandor

      I need to show/hide components based on other components state.
      Simplest example is 2 input boxes: The second one should not be rendered
      if the user input a certain value in the first.

      <h:inputText id=box1>
       <a4j:support reRender="box2"/>
      </h:inputText>
      
      <h:inputText id="box2" rendered="#{bean.isVisible}"/>
      


      The value of box1 will set bean.isVisible to be true or false and I expect box2
      to show or not...
      This is not working and the second box always shown.

      Any suggestions ?

        • 1. Re: reRender a component with rendered=

          Hi shandor,

          You need to specify a type of event eg onchange for the support tag.

          Try <a4j:support event="onchange" reRender="box2" />

          Thanks
          Victoria

          • 2. Re: reRender a component with rendered=

            You have three reasons why your code would not work.

            1 Victoria pointed to one of them. As soon as you do not specify the event attribute, the ajax call is never triggered. However, onchange is not good here. IE, instead of FF, invokes it only when you left the field. onkeyup is more suitable here

            2. JSF does not mark anyhow the place in the browser DOM is a component is not rendered. So, as soon as RichFaces has no idea where to insert re-rendered component, it will be not inserted. a4j:outputPanel helps to mark the place and solve the problem.
            See http://livedemo.exadel.com/richfaces-demo/richfaces/outputPanel.jsf

            3. JSF does not take a value from the model if the component in the component tree holds the submitted value. So, even you correct the first two problem you still have the example not working.
            RichFaces CookBook (http://wiki.jboss.org/auth/wiki/RichFacesCookbook) has an article about this:
            http://wiki.jboss.org/wiki/RichFacesTwoInputText

            So, who can post the solution how to correct the original code to make it working?

            • 3. Re: reRender a component with rendered=

              Humm, a challenge!

              
              <h:inputText id="box1" binding="#{RaiLei.textBoxExample}">
               <a4j:support event="onkeyup" reRender="box2" action="#{RaiLei.testVisible}" />
              </h:inputText>
              <a4j:outputPanel>
               <h:inputText id="box2" rendered="#{RaiLei.isVisible}" />
              </a4j:outputPanel>
              


               public HtmlInputText getTextBoxExample()
               {
               return textBoxExample;
               }
              
               public void setTextBoxExample(HtmlInputText textBoxExample)
               {
               this.textBoxExample = textBoxExample;
               }
              
               public boolean isIsVisible()
               {
               return true;
               }
              
               public String testVisible()
               {
               String temp = (String)this.textBoxExample.getValue();
               System.out.println(temp);
               return "testVisible";
               }
              


              didn't have time to get it to change visible on certain word, but would be easy now.

              Thanks
              Victoria

              • 4. Re: reRender a component with rendered=
                shandor

                Thanks much for your help Victoria, Sergey
                But one point is missed here...

                I think Victoria's code will not work because the ajaxSupport has the property reRender="box2".... and I suspect that reRender will not work for a component which changed it's "rendered" value

                My theory ( not tested yet ) is that the code will work if we replace reRender="box2" ---> reRender="outputPanel_ID"

                ... so the panel is always reRendered and box2 will show or hide according to it's rendered property value

                Someone care to comment on that ?



                • 5. Re: reRender a component with rendered=
                  shandor

                  My belief on this matter, which I will appreciate any scrutiny for :

                  In order to show/hide a component based on other component(s) state
                  you need to reRender the parent and not the component itself.

                  And this is unlike any other properties such as style, value etc. for which the component itself needs to be reRendered.

                  Please correct / praise

                  • 6. Re: reRender a component with rendered=

                     

                    "shandor" wrote:

                    In order to show/hide a component based on other component(s) state
                    you need to reRender the parent and not the component itself.


                    This is not true in general. You need to point to the one that is present on the page before re-rendering. So, the statement "always re-render the parent" is not correct.


                    Also, based on your previous reply, it looks like you miss the #3 point

                    • 7. Re: reRender a component with rendered=

                      Victoria, you miss the point #2 and the solution for #3 might be much more simple (i.e. without the binding)

                      • 8. Re: reRender a component with rendered=
                        shandor

                        Hi Sergey,

                        I am aware to the "Two text boxes" issue and solve that with ajaxSingle or region.

                        My question is regarding how to reRender components ( of any type ! ) whos render property might change between ajax requests.

                        I did not find any other way so far besides putting the component I would like to reRender inside an outputPanel and reRender the outputPanel rather than the actual component I am interested in.
                        I also think this is what you mean in your point #2 where you say that if the component is not rendered there is no place holder for it in the DOM

                        • 9. Re: reRender a component with rendered=
                          shandor

                          Hello again

                          I set up some testing code with the following:

                          <a4j:outputPanel layout="none">
                           <h:inputText id="box1" value="hide">
                           <a4j:support event="onchange" ajaxSingle="true" reRender="box2"/>
                           </h:inputText>
                          </a4j:outputPanel>
                          <a4j:outputPanel layout="none">
                           <h:inputText id="box2" value="bla" rendered="#{bean.box1hasSomeValue}">
                           </h:inputText>
                          </a4j:outputPanel>
                          



                          If initial conditions are that box2 has rendered="false" then setting the right value in box1 will cause box2 to show.
                          So far all is well and indeed I do not need to reRender the containing outputPanel, just the box2 itself.
                          However, now setting the value of box1 such that bean.box1hasSomeValue=false will not cause box2 to disappear.

                          ... so it works only from not rendered to rendered but not the other way around.

                          I instead of box2 I use a component of type a4j:commandButton then it does not work at all.


                          Is it expected ? a defect ?

                          Thanks for reading!