Struts Validator: Validating Two Fields Match
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.