6 Replies Latest reply on May 17, 2010 6:51 AM by Lavanya k

    Validating against 2 fields

    Dave Ellery Newbie

      Ok so I have been trying in vain for a day now to get this to work, Im trying to validate my 2 password fields, but all the example I try end up with bogus errors, though the root is probably that I just dont understand what is going on/wrong


      so far I have




       <s:decorate id="passwordField" template="/layout/edit.xhtml">
                           <ui:define name="label">Password</ui:define>
                           <h:inputSecret id="password"
                                  required="true"
                                      size="45"
                                 maxlength="45"
                                     value="#{memberHome.instance.password}"
                                      validator="#{memberValidator.validatePassword}" >
                               <f:attribute name="passwordId" value="memberProfile:confirmPassword" />
                               <f:validateLength minimum="6"/>
                               <a:support event="onblur" reRender="passwordField" bypassUpdates="true" ajaxSingle="true" />
                           </h:inputSecret>
                       </s:decorate>
                       
                       <s:decorate id="confirmPasswordField" template="/layout/edit.xhtml">
                           <ui:define name="label">Confirm Password</ui:define>
                           <h:inputSecret id="confirmPassword"
                                  required="true"
                                      size="45"
                                 maxlength="45"
                                      value="#{memberPasswordValidator.confirmPassword}"
                                      validator="#{memberValidator.validatePassword}" >
                               <f:attribute name="passwordId" value="memberProfile:password" />
                                    <f:validateLength minimum="6"/>
                               <a:support event="onblur" reRender="passwordField" bypassUpdates="true" ajaxSingle="true"/>
                           </h:inputSecret>
                       </s:decorate>



      and in my component



      @Name(value="memberValidator")
      @BypassInterceptors
      public class MemberValidator {
      
           public void validatePassword(FacesContext context, UIComponent component, Object value)
                     throws ValidatorException {
                
                 // Obtain the client ID of the first password field from f:attribute.
              String passwordId = (String) component.getAttributes().get("passwordId");
      
              // Find the actual JSF component for the client ID.
              UIInput passwordInput = (UIInput) context.getViewRoot().findComponent(passwordId);
      
              if( passwordInput != null ){
                   // Get its value, the entered password of the first field.
                   String password = (String) passwordInput.getValue();
           
                   // Cast the value of the entered password of the second field back to String.
                   String confirm = (String) value;
           
                   // Compare the first password with the second password.
                   if (!password.equals(confirm)) {
                       throw new ValidatorException(new FacesMessage("Passwords are not equal."));
                   }
           
                   // You can even validate the minimum password length here and throw accordingly.
                   // Or, if you're smart, calculate the password strength and throw accordingly ;)
              }
           }
           
           private String confirmPassword;
      
           public void setConfirmPassword(String confirmPassword) {
                this.confirmPassword = confirmPassword;
           }
           public String getConfirmPassword() {
                return confirmPassword;
           }
      
      
           
      }



      If someone could steer me in the right direction that'd be great.







        • 1. Re: Validating against 2 fields
          Leo van den berg Master

          Hi Dave,


          I think you're making it more complex than really necessary. I see you're using a Home component and the most simplest thing would be to create a subclass of the Home-class with an additional field for the passwordconfirmation. At the moment you type in the second field (confirmation) you can fire a simple validation in its setter (checking if both fields are the same) or you could do that after pressing a submit. In this specific case therre is really no need for an additional validator nor do you have to interact with the faces context, Seam can o that for you.


          Another small remrk is about the annotation you have on the clsss membervalidator. You're basically saying you want a Seam component with a specific name, but you don't want to use Seam interceptors for it.



          • 2. Re: Validating against 2 fields
            Dave Ellery Newbie

            Hi Leo,


            Thanks for the reply,


            But I am wanting to show the validation on the fly as with the other required fields, though if its not possible then I guess I can live with that.


            as for the @BypassInterceptors thats just left over from playing about with using the class as a registered validator.

            • 3. Re: Validating against 2 fields
              Dave Ellery Newbie

              ok sorted it out and now i have almost exactly what I want


              except when I use h:inputSecret  after validation is appears to clear the field out, which is no good



                               <s:decorate id="passwordField" template="/layout/edit.xhtml">
                                   <ui:define name="label">Password</ui:define>
                                   <h:inputText id="password"
                                          required="true"
                                              size="45"
                                         maxlength="45"
                                             value="#{memberHome.instance.password}"
                                             validator="#{memberValidator.validatePassword}" >
                                        <f:attribute name="passwordId" value="memberProfile:confirmPasswordField:confirmPassword" />
                                       <f:validateLength minimum="6"/>
                                       <a:support event="onblur" reRender="passwordField" bypassUpdates="true" ajaxSingle="true"/>
                                   </h:inputText>
                               </s:decorate>
                               
                               <s:decorate id="confirmPasswordField" template="/layout/edit.xhtml">
                                   <ui:define name="label">Confirm Password</ui:define>
                                   <h:inputText id="confirmPassword"
                                          required="true"
                                              size="45"
                                         maxlength="45"
                                         validator="#{memberValidator.validatePassword}">
                                            <f:validateLength minimum="6"/>
                                            <f:attribute name="passwordId" value="memberProfile:passwordField:password" />
                                            <a:support event="onblur" reRender="confirmPasswordField" bypassUpdates="true" ajaxSingle="true"/>
                                   </h:inputText>
                               </s:decorate>




              and the validator



              @Name("memberValidator")
              @Scope(ScopeType.PAGE)
              public class MemberValidator {
                   
                   public void validatePassword(FacesContext context, UIComponent component, Object value)
                             throws ValidatorException {
                        // Obtain the client ID of the first password field from f:attribute.
                      String passwordId = (String) component.getAttributes().get("passwordId");
              
                      // Find the actual JSF component for the client ID.
                      UIInput passwordInput = (UIInput) context.getViewRoot().findComponent(passwordId);
              
                      // Get its value, the entered password of the first field.
                      String password = (String) passwordInput.getValue();
                      
              
                      // Cast the value of the entered password of the second field back to String.
                      String confirm = (String) value;
                      
                     
              
                      // Compare the first password with the second password.
                      if ( confirm != null && password != null && !password.equals(confirm)) {
                          throw new ValidatorException(new FacesMessage("Passwords are not equal." ) );
                      }
              
                      // You can even validate the minimum password length here and throw accordingly.
                      // Or, if you're smart, calculate the password strength and throw accordingly ;)
                   }
                        
              }







              • 4. Re: Validating against 2 fields
                Vanesa Untermann Newbie
                Hi Dave,

                When you use h:inputSecret you should add redisplay=true to remain the contents of the field.

                • 6. Re: Validating against 2 fields
                  Lavanya k Newbie

                  Hi Dave,


                  What deos memberProfile refer to here in your code?


                  Thanks.