Jsf Seam validation
From Foochal
Contents |
Validating multiple fields using AJAX with individual validation rules
Suppose you have 2 fields, field1 and field2, which we would like to validate as the user is typing the input. Let's say field1 fails validation, we would like to display an error message. The tricky scenario is if user chooses to ignore this error message and proceeds to fill out field2. Now if field2 fails, you don't want the error message for field1 to get cleared. This may seem obvious, however, the defaults in ajax4j prevent this from happening.
So here's the code which makes it work:
<a4j:region>
<tr>
<th><label>Field1</label></th>
<td>
<h:inputText id="field1" required="true" label="Field1" value="#{myBean.field1}">
<a4j:support event="onchange" limitToList="true" reRender="field1_message" />
</h:inputText>
</td>
</tr>
<tr class="error">
<th></th>
<td>
<a4j:outputPanel id="field1_message" ajaxRendered="true">
<h:message for="field1" styleClass="error" />
</a4j:outputPanel></td>
</tr>
</a4j:region>
The key part here is limitToList, which limits the ajax response to fields specified in the reRender attribute
<a4j:support event="onchange" limitToList="true" reRender="field1_message" />
Cross field validation using ajax
In the following example we will validate if the 2 password fields match.
Xhtml code for password1. Here we add an ajax support to update the password as soon as it is changed. This makes sure that the new password1 field value is stored in the component tree immediately.
<h:inputSecret value="#{myBean.password1}" id="password1">
<a4j:support event="onchange" />
</h:inputSecret>
Xhtml code for password2. Here we add a custom jsf validator as per the JSF standards. Also, this validator is invoked immediately by adding ajax4j support.
<h:inputSecret value="#{myBean.password2}" id="password2" validator="#{myBean.passwordMatchValidator}>
<a4j:support event="onchange" />
</h:inputSecret>
Here's the java code for myBean:
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import org.apache.commons.lang.StringUtils;
import org.jboss.seam.annotations.Name;
@Name("myBean")
public class MyBean {
private String password1;
private String password2;
private String getPassword1() {
return this.password1;
}
private void setPassword1(String password1) {
this.password1 = password1;
}
private String getPassword2() {
return this.password2;
}
private void setPassword2(String password2) {
this.password2 = password2;
}
public void passwordMatchValidator(FacesContext context,
UIComponent toValidate, Object value) throws ValidatorException {
String valueStr = value.toString();
boolean valid = StringUtils.equals(this.password1, valueStr);
if (!valid) {
FacesMessage message = new FacesMessage();
message.setDetail("Passwords do not match");
message.setSummary("Passwords do not match");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
How it works
- User fills in password1.
- The "onchange" event makes an ajax call to update the field value and password1 is stored on to the backend component tree
- User fills in password2
- The "onchange" event makes an ajax call to update the field value.
- The "passwordMatchValidator" is called by JSF which does the validation.
Custom validation message for required="true"
Using requiredMessage
JSF provides an attribute called 'requiredMessage' to let you specify the error message when required fields are missed
<h:inputText required="true" requiredMessage="Password is required" />
messages.properties
Adding the following line to the messages.properties overrides the default required message application-wide.
javax.faces.component.UIInput.REQUIRED={0} is required
Further, you can customize the placeholder {0} by specifying the label attribute of the input field.
<h:inputText required="true" label="Your password" />
results in the error message
Your password is required
References
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=120754&postdays=0&postorder=asc&start=0

