Jayesh
Jayesh

Reputation: 6111

setting field to blank after validation in jsf

I am new to JSF and going through one JSF application.

I want to validate one Password field for Blank string.

I know instead of doing it in Javascript, I am calling a function for validation.

My need is, if value of the password field is blank then it is validated from validator function till now it is going correctly but after validation when it come =s to UI bav=ck at that time password field should be empty.

If password field is empty(contains spaces only) then i want it to set it as blank or else keep data as it is.

My try till now, JSF view page singin.xhtml

                    <h:outputText styleClass="outputBox" style="margin: 3px;"
                        value="Password" />
                    <h:inputSecret id="password" required="true" 
                        requiredMessage="Please enter your password"
                        value="#{userActionManager.dto.password}" 
                        validator="#{userActionManager.validateSamePassword}">

                            <a4j:ajax event="change" execute="@this" bypassUpdates="true" />
                    </h:inputSecret>

Validator method.

    public void validateSamePassword(FacesContext fc, UIComponent component, Object obj) {
         System.out.println("UserActionManager.validateSamePassword()");

         String confirmPassword = (String)obj;
         System.out.println("Password is :" + confirmPassword);
            if(confirmPassword!=null && confirmPassword.trim().equals("")) {
              FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Password cannot be blank", " detail Passwords do not match!");

//            System.out.println(component.getFamily());
//            String field1Id = (String) component.getAttributes().get("password");

              // Find the actual JSF component for the client ID.
//            UIInput textInput = (UIInput) fc.getViewRoot().findComponent("password");
//            textInput.setValue("");

              dto.setPassword(null);

              throw new ValidatorException(message);
            }else{
                dto.setPassword(confirmPassword);
            }
    }

I tried option dto.setPassword(null); but when it returns to view, blank spaces in password field is still there and i have to manually remove.

what I am missing?

Upvotes: 1

Views: 3613

Answers (2)

BalusC
BalusC

Reputation: 1108722

If a component is marked invalid, then it won't redisplay the model value (in your case, the value from the dto). Instead, it will redisplay its submitted value. You just need to set the submitted value to an empty string.

Replace

dto.setPassword(null);

by

((UIInput) component).setSubmittedValue("");

Upvotes: 1

kolossus
kolossus

Reputation: 20691

Within your validator, call resetValue() on the instance of UIComponent passed as argument

public void validateSamePassword(FacesContext fc, UIComponent component, Object obj) {
     System.out.println("UserActionManager.validateSamePassword()");

     String confirmPassword = (String)obj;
     System.out.println("Password is :" + confirmPassword);
        if(confirmPassword!=null && confirmPassword.trim().equals("")) {
          FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,   "Password cannot be blank", " detail Passwords do not match!");

          component.resetValue();

          throw new ValidatorException(message);
        }else{
            dto.setPassword(confirmPassword);
        }
}

dto.setPassword(null) will not affect the value in the password box as input components are designed to preserve the values that caused them to fail validation. resetValue() is a method that will cause the component to reset it's value to an uninitialized state

EDIT: The solution above resets the input value prematurely. Technically, validation doesn't fail until a ValidationException is thrown. To effectively reset the field:

  1. Define a listener event that will reset the value of the component only after validation fails

    public void resetPwd(ComponentSystemEvent evt) throws IOException {
    HtmlInputSecret txt = (HtmlInputSecret) evt.getComponent();
    if(!txt.isValid()){ //make sure that the validation failed 
        txt.resetValue();
       }
    
    }
    
  2. Attach the listener event to the postValidate event listener on the password component. This will ensure that the value is reset only after validation has failed.

      <h:inputSecret id="password" required="true" 
                    requiredMessage="Please enter your password"
                    value="#{userActionManager.dto.password}" 
                    validator="#{userActionManager.validateSamePassword}">
                        <f:event name="postValidate" listener="#{userActionManager.resetPwd}"/>
                        <a4j:ajax event="change" execute="@this" bypassUpdates="true" />
                </h:inputSecret>
    

The key here is to reset the value at the right time. Other options for time include the preRenderView event and postAddToView event. It's all in the timing

Upvotes: 1

Related Questions