4 Replies Latest reply on Dec 28, 2009 2:49 AM by Ievgen Nekrashevych

    a4j:support with ajaxSingle and process to validate fields

    Ievgen Nekrashevych Newbie

      Hello.

       

      I have my jsp page code written below (snippet from it):

       

      ...

      <h:form id="register" binding="#{authenticator.registerForm}"

      rendered="false">

                <%-- Password --%>

               <h:outputLabel value="Password:" for="password" />

               <h:inputSecret id="password" value="#{authenticator.user.password}"

                   required="true" requiredMessage="Password is required.">

                </h:inputSecret>

                <a4j:outputPanel id="errorForRegisterPassword">

                       <h:message for="password" errorClass="error" />

                 </a4j:outputPanel>

       

                 <%-- Confirm --%>

                <h:outputLabel value="Confirm:" for="confirm" />

                <h:inputSecret id="confirm" value="#{authenticator.user.confirm}"

                     required="true" requiredMessage="Confirm is required.">

                     <f:attribute name="passId" value="register:password" />

                     <f:validator validatorId="validator.confirm" />               <%-- MY VALIDATOR --%>

                     <a4j:support event="onblur"  

                          reRender="errorForRegisterConfirm, errorForRegisterPassword"

                          process="register:password" ajaxSingle="true" />

      <%-- Process validation on onblur event and also need to send register:password inputSecret for confirm can be compared to password (done by process attribute --%>

                </h:inputSecret>

                <a4j:outputPanel id="errorForRegisterConfirm">

                     <h:message for="confirm" errorClass="error" />

                </a4j:outputPanel>

       

                <%-- There goes other fields and commandButton --%>

      </h:form>

      ...

       

       

      I have my validator code (he does simply one thing - finds the component in a ViewRoot by id that was passed by attribute in this component and compares the value with the component value and if not equals - proceeds a Exception:

       

      public class ConfirmValidator implements Validator {

       

      public void validate(FacesContext context, UIComponent component,

      Object value) throws ValidatorException {

           String pass = (String) component.getAttributes().get("passId");

           UIInput passwordInput = (UIInput) context.getViewRoot().findComponent(pass);

           String password = (String) passwordInput.getLocalValue();

           String confirm = (String) value;

           if (password == null || !password.equals(confirm)) {

           throw new ValidatorException(new FacesMessage("Passwords and confirm doesn't equal."));

      }

      }

      }

       

      Two beans "authenticator" that holds reference to another "user" bean are request scope beans.

       

      The issue is that when you first input "1" (or some another symbol) into password field, then focus on confirm field, and input there "1" (the same symbol as in password) and get focus on another element (do a blur event to send a request) the sever will send you "Passwords and confirm doesn't equal." because value of password string in ConfirmValidator will be null --> Validation unsuccessful.

      And more interesting. If you focus and blur again (do change nothing) ConfirmValidator will get the "1" string for the input value of password input component. --> Validation successfull.

      And if you do blur again - again null. And so on.

       

      But if throw away ajaxOnly and process attributes - everything works ok. Validates everytime you do blur event.

       

      Why? Is that a bug? Can somebody explain me this? What is happening there inside?