2 Replies Latest reply on Feb 26, 2009 5:15 PM by bcowdery.bcowdery.gmail.com

    Seam fails to reRender content for an empty entity

    bcowdery.bcowdery.gmail.com

      Hi All,


      I'm writing a simple e-mailer with Seam 2.0.2.GA and RichFaces and I'm running into issues with the AJAX support. It won't reRender unless there is content in the Entity for the area I'm attempting to reRender, which is a problem because its a changing list that can be filled and emptied at will.


      I have it set up so that you can add multiple addresses by clicking an add button beside a text field, which builds a list of addresses reRenders a recipient area to include the newly added address.



      <s:decorate id="addToAddressDecoration" template="layout/edit.xhtml">
          <ui:define name="label">To:</ui:define>
      
          <h:inputText id="to"
                       value="#{emailAddressBean.to}"
                       size="80">
          </h:inputText>
      
          <a:commandLink action="#{emailHome.addToAddress(emailAddressBean.to)}"
                         reRender="addToAddressDecoration,recipientsDecoration"
                         value="Add"                               
                         title="click to add"/>
      </s:decorate>




      You can click an added address to remove it and again, it reRenders the recipient area to show the change.



      <s:decorate id="recipientsDecoration" template="layout/edit.xhtml">
          <ui:define name="label">Recipients:</ui:define>
      
          <h:outputText value="No recipients" rendered="#{empty emailHome.instance.recipients}"/>
      
          <ui:repeat value="#{emailHome.instance.to}" var="to">
              <a:commandLink value="to: #{to}; "
                             action="#{emailHome.removeToAddress(to)}"
                             reRender="recipientsDecoration"
                             bypassUpdates="true"                                   
                             title="click to remove"/>
          </ui:repeat>
      </s:decorate>



      Note that emailAddressBean is a backing bean used to pass the address to a method in EmailHome, which updates the list.


      The problem is that when i try and remove the last address in the list (the final element, which leaves the list empty), the field won't re-render! I've added logging to my action and it does remove the clicked address from the entity's list, however the view is never updated.


      Any help will be greatly appreciated.

        • 1. Re: Seam fails to reRender content for an empty entity

          Hi, I have exactly the same problem. Did you find the solution? Thank you!

          • 2. Re: Seam fails to reRender content for an empty entity
            bcowdery.bcowdery.gmail.com

            Yes I did, although it feels like more of a workaround than a solution.


            Wrap the input area in an ajax4jsf region and the output area in an ajax4jsf outputPanel. The point of this is to limit the extent of the component tree processing when the ajax request comes in. I found that because I had multiple fields on the page, if any single field failed validation it held up the entire ajax request.


            As for why the outputPanel works, i can think of two reasons (which may or may not be correct, I'm still new to JSF :P). One is that the outputPanel with ajaxRendered="true" will ALWAYS re-render its content on an ajax request. The other is that the outputPanel can act as a placeholder for UIComponents which have not been rendered (either because of zero content or rendered="false") and so cannot act as ajax targets.


            Either way... the below solution works. If someone else has a better solution or if i got the above explanation wrong, I'd love to hear it.


            Input area


            <s:decorate id="addToAddressDecoration" template="layout/edit.xhtml">
                <ui:define name="label">To:</ui:define>
                <a:region>
                    <h:inputText id="to"
                                 value="#{emailAddressBean.to}"
                                 size="80">
                    </h:inputText>
                    <a:commandLink action="#{emailHome.addToAddress(emailAddressBean.to)}"
                                   reRender="addToAddressDecoration,recipientsDecoration"
                                   value="Add"
                                   title="click to add"/>
                </a:region>
            </s:decorate>




            Output         



            <a:outputPanel ajaxRendered="true">
                <s:decorate id="recipientsDecoration" template="layout/edit.xhtml">
                    <ui:define name="label">Recipients:</ui:define>
            
                    <h:outputText value="No recipients" rendered="#{empty emailHome.instance.recipients}"/>
            
                    <ui:repeat value="#{emailHome.instance.to}" var="to">
                        <a:commandLink value="to: #{to}; "
                                       action="#{emailHome.removeToAddress(to)}"
                                       reRender="recipientsDecoration"
                                       bypassUpdates="true"
                                      title="click to remove"/>
                    </ui:repeat>
                </s:decorate>
            </a:outputPanel>




            Note that my complete page has fields and for CC and BCC addresses, which is why there is the need for the 'recipients' list - however I've stripped these out to simplify the example.


            Enjoy!