You can also equip your custom validators with JavaScript functions that perform client side validation. This is illustrated in the app05g application discussed in this section. This application is similar to app05f except that the custom validator supports client-side validation.
The steps to modify app05f into app05g are as follows. First, you need to write your JavaScript function. Then, you need to register it in a validator rules file. Lastly, you must use the HTML Tag Library’s javascript tag to generate to the JavaScript function. These steps are detailed in the following subsections.
The JavaScript function for validating passwords on the client-side is stored in the validateSecurePassword.js file under the WEB-INF/classes directory. The function must meet the following requirements:
The validateSecurePassword function is given in Listing 5.13. Familiarity with JavaScript is assumed to understand this function.
Lisitng 5.13: The JavaScript function
function validateSecurePassword(form) {
var isValid = false;
var containsNumeric = false;
var containsNonNumeric = false;
var focusField = null;
var i = 0;
var fields = new Array();
var formName = form.getAttributeNode("name");
oPassword = eval('new ' + formName.value + '_securepassword()');
for (x in oPassword) {
var field = form[oPassword[x][0]];
if ((field.type == 'hidden' || field.type == 'text' ||
field.type == 'textarea' || field.type == 'file' ||
field.type == 'checkbox' || field.type == 'select-one' ||
field.type == 'password') && field.disabled == false) {
var value = field.value;
isValid = false;
containsNumeric = false;
containsNonNumeric = false;
var length = parseInt(oPassword[x][2]("minLength"));
if (field.value.length >= length) {
var n = 0;
while(n < value.length && !isValid) {
ch = value.charAt(n);
if (isNumeric(ch))
containsNumeric = true;
else
containsNonNumeric = true;
if (containsNumeric && containsNonNumeric)
isValid = true;
n++;
} // while loop closing
if (!isValid) {
if (i==0)
focusField = field;
fields[i++] = oPassword[x][1];
}
} // if field.value.length closing
else {
if (i==0)
focusField = field;
fields[i++] = oPassword[x][1];
}
} // if field.type closing
} // for loop closing
if (fields.length > 0) {
isValid = false;
focusField.focus();
alert(fields.join('\n'));
}
else
isValid = true;
return isValid;
}
function isNumeric(ch) {
return (ch >= '0' && ch <= '9');
}
Just like in app05f, you need to register your custom validator before you can use it. Listing 5.14 presents the myValidator-rules.xml file (in WEB-INF) that registers the custom validator.
Listing 5.14: Registering your custom validator in app05g
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
<global>
<validator name="securepassword"
classname="app05g.validator.MyCustomValidator"
method="validateSecurePassword"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionMessages,
javax.servlet.http.HttpServletRequest"
msg="errors.securePassword"
jsFunction="app05g.validator.javascript.validateSecurePassword"
/>
</global>
</form-validation>
The difference between the validator rule file in Listing 15.4 and the one in Listing 5.10 is that in the former you have the jsFunction attribute inside the validator element. The jsFunction attribute specifies the path to the JavaScript file, without the .js extension and relative to WEB-INF/classes, that contains the JavaScript function used to validate input at client side.
The displayCreatePasswordForm.jsp page in Listing 5.15 shows how you can use the custom validator with client side validation. Notice that we have added a javascript element and added the onsubmit attribute to the form element.
Listing 5.15: The displayCreatePasswordForm.jsp page
<%@ taglib uri="/tags/struts-html" prefix="html"%> <html> <body> <html:javascript formName="passwordForm"/> <html:form action="/createPassword" onsubmit="return validatePasswordForm(this)"> <table> <tr> <td>Password:</td> <td><html:text property="password"/></td> </tr> <tr> <td colspan="2"><html:submit>Ok</html:submit></td> </tr> </table> </html:form> </body> </html>
You can run the app05g application by invoking the following URL:
http://localhost:8080/app05g/displayCreatePasswordForm.do