Tiny
Tiny

Reputation: 27899

Disable validation, if the current UIInput component has a null or empty value

I need to validate a length of the value held by a UIInput component only if the value of that UIInput component is either null or an empty.

The length validator - <f:validateLength> should be skipped / bypassed, in case the value is null or empty.

I have tried the following approach with no success.

<p:inputTextarea id="address" autoResize="false" value="#{testManagedBean.address}" maxlength="1000" minQueryLength="10" cols="35" rows="7">
    <f:validateLength minimum="5" maximum="1000" disabled="#{empty testManagedBean.address}"/>
</p:inputTextarea>

<p:message for="address" display="both" showSummary="false"/>
<p:commandButton value="Submit" actionListener="#{testManagedBean.action}"/>

The bean:

@ManagedBean
@ViewScoped
public final class TestManagedBean implements Serializable
{
    private String address;
    private static final long serialVersionUID = 1L;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void action() {
        System.out.println("action() called.");
    }
}

This field - "address" is actually optional but if some users provide an input then, it should contain minimum of five characters in length.


EDIT:

I'm using disabled="#{empty param['form:address']}" to disable the validator, when the UIInput component has a null or empty value (not to dig further for a better way as this works anyway).

Upvotes: 0

Views: 5345

Answers (2)

kolossus
kolossus

Reputation: 20691

You're on the right track, but you're not pulling the value off the component properly.

Bind the component to the page scope and retrieve the value like so:

<p:inputTextarea id="address" binding="#{theAddress}" autoResize="false" value="#{testManagedBean.address}" maxlength="1000" minQueryLength="10" cols="35" rows="7">
    <f:validateLength minimum="5" maximum="1000" disabled="#{empty theAddress.getSubmittedValue()}"/>
</p:inputTextarea>

Your current approach requires the textArea's value to be written to the backing bean. This can't happen until validation occurs (remember: testManagedBean.address is available only after successful validation); you're expecting that same value during validation: catch 22.

Upvotes: 1

rion18
rion18

Reputation: 1221

No need for OmniFaces: you can create your own validator. You have to create a class that implements the javax.faces.validator.Validator interface, overrides the validate() method, and call it in your xhtml page. An alternative would be:

<p:inputTextarea id="address" autoResize="false" value="#{testManagedBean.address}" maxlength="1000" minQueryLength="10" cols="35" rows="7">
  <f:validator validatorId="myValidator"/>
</p:inputTextarea>

The validator class:

@FacesValidator("myValidator")
public class MyValidator Validator{

  @Override
  public void validate(FacesContext context, UIComponent component, Object value) 
        throws ValidatorException {
    String myValue = value.toString();
    if(myValue != null && !myValue.isEmpty() && (myValue.length() <= 5 || myValue.length() >= 1000)){
      throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
          "MyValidator Error: ", 
          "This error appears if your input has less than 5 chars or more than 1000."));
    }
  }
}

Upvotes: 2

Related Questions