3 Replies Latest reply on May 28, 2008 4:19 PM by Jason Long

    How to force Rerender even if validation fails?

    Jason Long Master

      Moved from A4JSF forum.

      See http://www.jboss.com/index.html?module=bb&op=viewforum&f=259 for initial posting.

      I have read many posts and wiki articles on this and I believe my problem is explained here http://wiki.jboss.org/wiki/RichFacesTwoInputText

      I will post some simplified code examples below. This is all done with facelets templates and is not working code. It is only to describe my problem. There are some errors there, but all works in my code except clearing the value from the input components.

      I have a data grid that is based on ExtendedDataModel.

      I open an edit modal as follows:

       <a4j:form id="selectContactForm">
       <a4j:commandButton image="images/buttons/edit.gif" title="Edit" action="#{listContactSearch.select(contactL)}" oncomplete="javascript:Richfaces.showModalPanel('editContactPanel',{left:'auto', top:'auto'});" reRender="editContactForm"/>
       </a4j:form>
      


      Inside the modal panel
       <a4j:form id="editContactForm">
       <rich:messages id="error" styleClass="hidden"/>
       <h:panelGrid columns="3">
      
       <h:outputText value="time" />
       <h:outputText value="#{currentDate}" converter="versionConverter" id="testCurrentDateOuter" />
       <h:outputText value=" " />
      
       <h:outputText value="company:" />
       <h:inputText id="company_inputText" value="#{contactEdit.company}" />
       <h:outputText id="company_outputText" value="#{contactEdit.company}" />
      
       <h:outputText value="phone:" />
       <h:inputText id="company_it" value="#{contactEdit.phone}" />
       <h:outputText id="company_ot" value="#{contactEdit.phone}" />
      
       <a4j:commandButton rendered="#{contactEdit.id!=null}" id="updateContact" image="images/buttons/create.gif" oncomplete="windowclose('#{formId}:error','#{panelId}');" title="Update Contact" action="#{listContactSearch.update(contactEdit)}" reRender="editContactForm,contactListGrid" />
       <a4j:commandButton rendered="#{contactEdit.id!=null}" id="deleteContact" image="images/buttons/delitem.gif" oncomplete="windowclose('editContactForm:error','#{panelId}');" title="Delete Contact" action="#{listContactSearch.delete(contactEdit)}" reRender="editContactForm,contactListGrid" />
       <h:outputText value="?" />
       </h:panelGrid>
       </a4j:form>


      Outjects the relevant row to load the form in the modal panel.
      action="#{listContactSearch.select(contactL)}"

      This works.

      I added a outputText that renders the value that is supposed to be in the input field.

      contactEdit.company is a String and never fails validation.
      contactEdit.phone is a Long and will fail if a letter is typed in this field.

      So if I open the modal and cause a JSF validation error for contactEdit.phone, and then close the modal panel and try to edit another contact contactEdit.phone show the new value and matches what the output Text shows for contactEdit.phone. However, contactEdit.company shows the old value in the inputText and the correct value in outputText.

      This will cause contact data to be scrambled as there are many other fields relating to the contact and can overlap.

      Please help me to understand JSF better so that I can get this to work. I also need to know how to make this work for select components.

      I am assuming that one of the other three places, probably the JSF 'local value' described in the wiki article.

      Any help would be greatly appreciated.

        • 1. Re: How to force Rerender even if validation fails?
          Jason Long Master

          I am thinking about trying binding for the input components, but I am not sure how it will work.

          Can this be set up in a way that all of my fields will act this way without having to code each one separately?

          • 2. Re: How to force Rerender even if validation fails?
            Jason Long Master

            I have been trying to do something like http://www.javabeat.net/articles/19-introduction-to-ajax4jsf-3.html
            , but bind to the form instead of individual input fields.

            I have been trying binding the form as follows:

            <a4j:form id="#{formId}" binding="#{baseAjaxForm.ajaxForm}">


            to the following Seam component.

            @Name("baseAjaxForm")
            public class BaseAjaxForm
            {
             @Logger Log log;
             private AjaxForm ajaxForm;
             public AjaxForm getAjaxForm() { return ajaxForm; }
             public void setAjaxForm(AjaxForm ajaxForm) { this.ajaxForm = ajaxForm; }
            
             @Observer("reset.ajax.form")
             public void resetAjaxForm()
             {
             log.info("reset.ajax.form");
             if(ajaxForm!=null)
             {
             recurseTree(ajaxForm);
             }
             }
            
             private void recurseTree(UIComponent uic)
             {
             log.info(uic);
             if (uic instanceof HtmlInputText)
             {
             HtmlInputText htmlInputText = (HtmlInputText) uic;
             log.info("found: "+htmlInputText);
             htmlInputText.setSubmittedValue(null);
             }
             for (UIComponent uic2 : uic.getChildren())
             {
             recurseTree(uic2);
             }
             }
            
             private void printChildren(UIComponent uic3)
             {
             for(UIComponent uic2 : uic3.getChildren())
             {
             log.info(uic2);
             }
             }
            
            }


            When I select a new item from the list I call

            public void resetAjaxForm()


            This runs fine and finds all of the HtmlInputText components and calls

            htmlInputText.setSubmittedValue(null);


            However, this does not reset the values for the input fields.

            Am I missing something?

            • 3. Re: How to force Rerender even if validation fails?
              Jason Long Master

              I found a solution

              I needed to call

              uiInput.setValue(null);


              I generalized this too work with UIInput.

              Is this a good approach?
              Can anyone see any problems caused by this?
              Can a more general approach used?


              See revised code below.

              @Name("baseAjaxForm")
              public class BaseAjaxForm
              {
               @Logger Log log;
               private AjaxForm ajaxForm;
               public AjaxForm getAjaxForm() { return ajaxForm; }
               public void setAjaxForm(AjaxForm ajaxForm) { this.ajaxForm = ajaxForm; }
              
               @Observer("reset.ajax.form")
               public void resetDatascroller()
               {
               log.info("reset.ajax.form");
               if(ajaxForm!=null)
               {
               recurseTree(ajaxForm);
               }
               }
              
               private void recurseTree(UIComponent uic)
               {
               if (uic instanceof UIInput)
               {
               UIInput uiInput = (UIInput) uic;
               uiInput.setSubmittedValue(null);
               uiInput.setValue(null);
               }
               for (UIComponent uic2 : uic.getChildren())
               {
               recurseTree(uic2);
               }
               }
              
              }