In the Struts Validator Guide, there is a section on how to create a pluggable validator that matches two fields. I've been using this server-side validator (as shown in the example) to do password/confirm password validation. This has worked great for me, but I've always wanted the Validator to have the client-side JavaScript method for it too. I wrote my own that just compared the two fields, but it's not the same as having one rendered for you (from validator-rules.xml
). So yesterday, I did some tinkering and figured out how to add the JavaScript method to validator-rules.xml
. So here's how to configure the whole thing (most of this is contained in the Validator Guide, save the JavaScript).
How To Add a TwoFields Validator
Step 1: Create a class with a validateTwoFields
method. In my code, my class is ValidationUtil
and has the following method:
public static boolean validateTwoFields(Object bean, ValidatorAction va,
Field field, ActionErrors errors,
HttpServletRequest request) {
String value =
ValidatorUtil.getValueAsString(bean, field.getProperty());
String sProperty2 = field.getVarValue("secondProperty");
String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);
if (!GenericValidator.isBlankOrNull(value)) {
try {
if (!value.equals(value2)) {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
} catch (Exception e) {
errors.add(field.getKey(),
Resources.getActionError(request, va, field));
return false;
}
}
return true;
}
Step 2: Edit validator-rules.xml
to contain the "twofields" rule.
<validator name="twofields"
classname="org.appfuse.webapp.util.ValidationUtil" method="validateTwoFields"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
depends="required" msg="errors.twofields">
<javascript><![CDATA[
function validateTwoFields(form) {
var bValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
oTwoFields = new twofields();
for (x in oTwoFields) {
var field = form[oTwoFields[x][0]];
var secondField = form[oTwoFields[x][2]("secondProperty")];
if (field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'select-one' ||
field.type == 'radio' ||
field.type == 'password') {
var value;
var secondValue;
// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
value = field.options[si].value;
secondValue = secondField.options[si].value;
} else {
value = field.value;
secondValue = secondField.value;
}
if (value != secondValue) {
if (i == 0) {
focusField = field;
}
fields[i++] = oTwoFields[x][1];
bValid = false;
}
}
}
if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}
return bValid;
}]]></javascript>
</validator>
Step 3: Configure validation for your form in validation.xml
:
<field property="password"
depends="required,twofields">
<msg
name="required"
key="errors.required"/>
<msg
name="twofields"
key="errors.twofields"/>
<arg0 key="userForm.password"/>
<arg1
key="userForm.confirmPassword"
/>
<var>
<var-name>secondProperty</var-name>
<var-value>confirmPassword</var-value>
</var>
</field>
Where errors.twofields=The '{0}' field has to have the same value as the '{1}' field. An alternative to Step 3 is to use XDoclet to generate your validation.xml
. This requires (1) configuring XDoclet (of course) and (2) adding some @struts
tags to your form on the setPassword
method.
/**
* Returns the password.
* @return String
*
* @struts.validator type="required" msgkey="errors.required"
* @struts.validator type="twofields" msgkey="errors.twofields"
* @struts.validator-args arg1resource="userForm.password"
* @struts.validator-args arg1resource="userForm.confirmPassword"
* @struts.validator-var name="secondProperty" value="confirmPassword"
*/
public String setPassword() {
return password;
}
I've sent this as a proposal to the struts-dev mailing list yesterday, but haven't heard anything yet. Enjoy!
Update: You'll need to update ValidationUtil.java and validator-rules-custom.xml for Struts 1.2. Full files: ValidationUtil.java and validation-rules-custom.xml.