9 Replies Latest reply on Apr 18, 2011 4:50 PM by sebulaki

    Conditional Rendering: HowTo?

    sebulaki

      Hi everybody!

       

      Please look at the following Code Snippet:

       

      <h:form>
          <h:panelGrid columns="2">
              <h:inputText value="#{vehicleBean.pin}" />
              <a4j:commandButton action="#{vehicleBean.loadVehiclesByPin}" render="results"/>
          </h:panelGrid>
      </h:form>
      <a4j:outputPanel id="results">
          <rich:dataTable value="#{vehicleBean.vehicles}" rendered="#{not empty vehicleBean.vehicles}">
              ...
          </rich:dataTable>
      </a4j:outputPanel>

       

      When I press the button an Ajax request is sent to load some business entities. They are displayed in a rich:dataTable which is only rendered if the corresponding array is not empty.

       

      This works for me in Chrome an Firefox 4 but not in IE9.

       

      So please tell me:

       

      • What is the correct approach to solve this kind of problem (with a conditionally rendered element)?
      • Which element(s) should I re-render?
      • Is the layout of my components correct?
      • The commandButton also has a execute attribute: When and why do I have to use this attribute?

       

      Greetings Sebi

        • 1. Conditional Rendering: HowTo?
          ilya_shaikovsky

          add layout="block" for the outputPanel.

           

          if not helps - check for js errors and/or a4j:log error entries logged.

           

          also consider that issue https://issues.jboss.org/browse/RF-10770

          • 2. Conditional Rendering: HowTo?
            fastroller

            Actually its a little more painful than that. You need to do something like:

             

                <h:panelGroup id="panelGroup" >

                    <a4j:outputPanel id="outputPanel" rendered="#{testBean.visible}" layout="block">

                        <p>A4j output panel visible</p>

                    </a4j:outputPanel>

                </h:panelGroup>

             

                   

                <a4j:commandButton id="toggle" value="Toggle" action="#{testBean.toggle}" render="panelGroup" execute="@this"/>

             

            If you change the render on the commandButton to outputPanel it does not render. Note, the TestBean is conversation scoped so it is retaining state between requests.

             

            I'm not really sure why this occurs. I'm going to guess that it is because the outputPanel is initially not rendered so is not included in the component tree so it is not built on the ajax action. By wrapping it with a parent component that is always in the tree it can be rendered. Perhaps Ilya you could shed some light on this?

            • 3. Conditional Rendering: HowTo?
              ilya_shaikovsky

              No, his initial code should not be added with additional wrappers. he already have <a4j:outputPanel id="results"> wrapper which already present at DOM tree (div with results id). And after button invocation table should be inserted there fine.

              • 4. Re: Conditional Rendering: HowTo?
                sebulaki

                Hi Ilya, Hi Andrew

                 

                Thanks for your responses!

                Cool, I didn't knew the a4j:log! :-)

                 

                In the generated HTML source I can see the tag <div id="results"/>.

                (Before the first Ajax request)

                 

                In IE9 the log produces the following output:

                 

                info [11:33:56.509]: Received 'begin' event from <input id=j_idt17:j_idt20 ...>

                info [11:33:59.050]: Received 'beforedomupdate' event from <input id=j_idt17:j_idt20 ...>

                error[11:33:59.057]: Received 'error@malformedXML' event from <input id=j_idt17:j_idt20 ...>

                error[11:33:59.059]: [200] undefined: undefined

                info [11:33:59.060]: Received 'complete' event from <input id=j_idt17:j_idt20 ...>

                 

                 

                Any Idea what the problem could be?

                • 5. Conditional Rendering: HowTo?
                  fastroller

                  Seriously I cannot toggle rendered without wrapping the panel with a rendered component. Take the example below:

                   

                      <a4j:outputPanel id="outputPanel" rendered="#{testBean.visible}" layout="block">

                          <p>A4j output panel visible</p>

                      </a4j:outputPanel>

                                 

                      <a4j:commandButton id="toggle" value="Toggle" action="#{testBean.toggle}" render="form:outputPanel" execute="@this"/>

                   

                  The testBean.visible is initially true. Pressing "Toggle" does not hide the panel. To me it looks like the first action to hide the panel does not transport an update as it is no longer visible in component tree. The log below shows that only the view state is updated. The output panel is not removed from the DOM tree in the browser. Pressing toggle again performs an update on a section that is already visible.

                   

                  This is why I suggest that wrapping the target panel works as it replaces the contents with either empty (not visible) or the content of the outputPanel.

                   

                   

                  info [19:48:42.415]: Received 'begin' event from <input id=form:toggle ...>

                  info [19:48:42.472]: Received 'beforedomupdate' event from <input id=form:toggle ...>

                  info [19:48:42.477]: Listing content of response changes element:
                  Element update for id=javax.faces.ViewState
                  <update id="javax.faces.ViewState"><![CDATA[7782037503692510418:8135255010768675014]]></update>

                  info [19:48:42.478]: Received 'success' event from <input id=form:toggle ...>

                  info [19:48:42.479]: Received 'complete' event from <input id=form:toggle ...>

                  info [19:48:50.221]: Received 'begin' event from <input id=form:toggle ...>

                  info [19:48:50.282]: Received 'beforedomupdate' event from <input id=form:toggle ...>

                  info [19:48:50.285]: Listing content of response changes element:
                  Element update for id=form:outputPanel
                  <update id="form:outputPanel"><![CDATA[<div id="form:outputPanel">               <p>A4j output panel visible</p></div>]]></update>
                  Element update for id=javax.faces.ViewState
                  <update id="javax.faces.ViewState"><![CDATA[7782037503692510418:8135255010768675014]]></update>

                  info [19:48:50.287]: Received 'success' event from <input id=form:toggle ...>

                  info [19:48:50.288]: Received 'complete' event from <input id=form:toggle ...>

                  • 6. Re: Conditional Rendering: HowTo?
                    sebulaki

                    Hi Andrew

                     

                    Yes, your example won't work as expected...

                     

                    See this extract from the RichFaces Developer Guide:

                     

                    As with most Ajax frameworks, you should not attempt to append or delete elements on a page using RichFaces Ajax, but should instead replace them. As such, elements that are rendered conditionally should not be targeted in the render attributes for Ajax controls. For successful updates, an element with the same identifier as in the response must exist on the page. If it is necessary to append code to a page, include a placeholder for it (an empty element).

                     

                    But in my case the outputPanel with id "results" is always visible! So it doesn't need an additional wrapper.

                     

                    But I still couldn't get it to work properly...

                     

                    Greetings Sebi

                    • 7. Re: Conditional Rendering: HowTo?
                      fastroller

                      Hi Sebastian,

                       

                      I guess I was talking a bit cross-purposes. I can't really help with IE9 as I run Linux.

                       

                      I can only make two suggestions. a) Give all your components ids so that you can better understand the log output. b) Try putting all the code inside the form.

                       

                      Good luck.

                      • 8. Re: Conditional Rendering: HowTo?
                        ilya_shaikovsky

                        Sebastian, found one more possible problem. panleGroup rendered as span by default and you using div inside. So generated html is not valid in that case. add layout=block to the panelGroup.

                         

                        Andrew - in his code there were wrapper (panelGroup) which he updated so that's why I said no need in additional outputPanel.

                        • 9. Re: Conditional Rendering: HowTo?
                          sebulaki

                          Hi

                           

                          add layout=block to the panelGroup.

                           

                          Unfortunately, that doesn't help...

                           

                          But:

                           

                          • Changing render="results" to render="@page" helps (But this is not very nice, isn't it?)
                          • Running IE in "compatibility mode" helps

                           

                          At the moment I have no time to continue working on this problem... But i'll post any news here.

                           

                          Greetings