1 Reply Latest reply on Jun 7, 2007 12:21 PM by Sergey Smirnov

    question for a4j:outputPanel

    liumin hu Master


      When attribute layout="none", and id ="someid", i can't reRender this outputPanel, a4j:log says cant find it. Is it normal?

        • 1. Re: question for a4j:outputPanel
          Sergey Smirnov Master

          Yes, it should work like that.

          Let me explain what is layout="none" is designed for and how it works:

          When the component is not rendered (rendered="false"), JSF does not render anything and browser DOM tree does not has a placeholder to mark the place where the component might locate if rendered becomes "true" next time.

          This is the source of the limitation why developers should avoid pointing with reRender to the component that has "rendered"attribute - when "rendered" becomes "true" and the result of rendering comes to the client with next Ajax response, the updating in failed because no place to insert.

          First approach is pointing to the parent component or using a4j:outputPanel as a wrapper and point to it.


          For example, if we have:

          <..... reRerender="wripper" />
          .....
          <rich:panel id="outer">
           <a4j:outputPanel id="wripper">
           <rich:panel id="inner" rendered="....">
           ....
           </rich:outputPanel>
           ....
          </rich:outputPanel>


          We will have in case of rendered="false"
          <div id="outer">
           <span id="wripper">
           </span>
           ......
          </div>


          in case of rendered="true", it will be:
          <div id="outer">
           <span id="wripper">
           <div id="inner">
           .....
           </div>
           </span>
           ......
          </div>


          Actually, the last code is invalid, because div cannot be surrounded with span according to the w3c spec. You can use layout="block" to correct this case. However,there will be still an extra div that is useless from the layout point of view.


          The solution is using the second approach - layout="none"


          The JSP code:

          <..... reRerender="inner" />
          .....
          <rich:panel id="outer">
           <a4j:outputPanel layout="none">
           <rich:panel id="inner" rendered="....">
           ....
           </rich:outputPanel>
           ....
          </rich:outputPanel>



          We will have in case of rendered="false"
          <div id="outer">
           <span id="inner" style="display:none" />
           ......
          </div>


          in case of rendered="true", it will be:
          <div id="outer">
           <div id="inner">
           .....
           </div>
           ......
          </div>


          Pay attention to the difference:

          In JSP:
          1.a) outputPanel has no it's own id defined (it might be, but no reason)
          1.b) reRender points directly to the inner panel

          In the DOM:
          2.a) invisible span is rendered and obtains the id of the non-rendered panel in case of rendered="false"
          2.b) nothing is rendered in case of rendered="true"

          ==
          So, layout="none" has a special behavior:
          outputPanel layout="none" marks the placeholder in the browser DOM tree when rendered attribute of the child component equals "false" and does not render itself at all if child component is rendered.

          Finally, I can explain you why a4j:log says it is not found. It happens because id="someid" never appears in the browser. See 2.a and 2.b above.