3 Replies Latest reply on Dec 11, 2008 9:39 AM by tnl77

    Problem with s:decorator, s:message and cancel button

      Hi seam forum!


      I experienced a problem canceling an operation and resetting the form to default values. I will explain it with a little example: I have a simple form with one save and one cancel button. When the user clicks on the save button, the form shall be resetted. I am using ajax4jsf commandbuttons.


      <h:form>
      <s:decorate template="/include/formFieldDecorate.xhtml">
        <ui:define name="label">Duration</ui:define>
        <h:inputText id="duration" size="5" value="#{testHome.instance.duration}"  required="true" />
      </s:decorate>
      <s:div>
        <a4j:commandButton value="Save" action="#{testHome.persist}" reRender="testForm" />
        <a4j:commandLink action="#{testHome.reset}" reRender="testForm" ajaxSingle="true" />
      </s:div>
      </h:form>
      



      The first problem was that hitting the cancel button causes validation errors. That problem was easy to solve by adding:

      immediate="true"

      Unfortuantely, setting immediate to true has the sideeffect that the action method in my backing bean succesfully resets the field values, but reRender doesn't show it.


      I tried another solution by adding

      ajaxSingle="true"

      to the cancel button. That works almost perfect except that the
      #{invalid}

      expression within the s:decoration  tag doesn't recognize the changes. The error messages become invisible but the error styles are still applied.


      Summary:
      Immediate works except that the new values were not applied to the form.
      ajaxSingle works except that the s:decorator invalid expression recognizes it.


      How can I solve the problem?

        • 1. Re: Problem with s:decorator, s:message and cancel button

          Sorry, one mistake while preparing a simplified example: I forgot the id for the h:form. So it must look like:


          <h:form id="testForm">
          



          • 2. Re: Problem with s:decorator, s:message and cancel button

            A short status update. As explained, I guess that the #{invalid} will not be reset when using ajaxSingle="true" instead of immediate="true". I looked at the sources of s:decorator and tried to reset #{invalid} manually by using the following codes in the reset method:


            
            facesMessages.clear();
            
            // Contexts.getEventContext().set("invalid", false);
            Contexts.getEventContext().remove("invalid");
            



            Unfortunately, it didn't work. Maybe I am completely wrong with my assumptions with #{invalid}?

            • 3. Re: Problem with s:decorator, s:message and cancel button
              tnl77

              Hi Vassiliy!


              I faced with the same problem and it seems that I have solve it.


              I also used ajaxSingle = "true" for my cancel button and in the action for this button I called following function with FacesContext.getCurrentInstance().getViewRoot() as argument.


              public static void clearInvalidState(UIComponent root) {
                   for (UIComponent component : root.getChildren()) {
                       if (component instanceof EditableValueHolder) {
                           EditableValueHolder valueHolder = (EditableValueHolder)component;
                           valueHolder.setValid(true);
                       }
                       clearInvalidState(component);
                   }
              }