Validation

   

JSF 1.0 has strong support for server-side validation of a single component. However, if you want to carry out client-side validation or to validate relationships among components, you are on your own. The following sections tell you how you can overcome these issues.

How do I use the Struts framework for client-side validation?

A web application can validate user input inside the browser client or on the server. Client-side validation is more efficient. Users don't have to wait for the server to diagnose the error and render a response page. However, client-side validation requires downloading validation code into browsers, typically using JavaScript. Unfortunately, producing JavaScript code that runs in multiple browsers is a bit of a black art.

The HTML tags in JSF 1.0 do not provide client-side validation. If you want to add client-side validation to your application, you have two choices: use a third-party library or implement a custom solution.

In this section, we show you how you can use the client-side validator in the Struts framework together with JSF. You can download Struts from http://jakarta.apache.org/struts.

Using Struts gives you the advantage of using a set of well-debugged JavaScript routines. You will see on page 606 how you can write a validator that uses your own JavaScript code.

Here is an overview of the required steps for using Struts validation in a JSF application.

  1. Add the files struts.jar, commons-validator.jar, commons-lang.jar, and jakarta-oro.jar from the Struts distribution to the WEB-INF/lib directory of your web application.

  2. Add the following entry to your web.xml file:

     

     <servlet>   <servlet-name>action</servlet-name>   <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>   <init-param>     <param-name>config</param-name>     <param-value>/WEB-INF/struts-config.xml</param-value>   </init-param>   <load-on-startup>2</load-on-startup> </servlet> 

  3. Add a file WEB-INF/struts-config.xml that specifies the location of the validator configuration files and message bundles (see Listing 12-21).

  4. Add the file validator-rules.xml from the Struts distribution to the WEB-INF directory of your web application.

  5. Add a message bundle that specifies the text of the error messages (see Listing 12-22).

  6. In each JSF page that uses client-side validation, import the Struts HTML tag library:

     

     <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> 

    Add the following tag inside the head element of each form that requires client-side validation:

    <html:javascript formName="myForm"/>

    Here, myForm is a form name that you need to choose. Set the same form name as the ID of the h:form element. Also add an onsubmit attribute that calls the JavaScript function validateMyForm, like this:

    <h:form onsubmit="return validateMyForm(this);">

    Listing 12-24 shows an example.

  7. Provide a file validation.xml that contains all client-side validation rules of your application. You can see an example in Listing 12-24 on page 606. The file format is explained in http://jakarta.apache.org/struts/userGuide/dev_validator.html. Table 12-2 describes the client-side validators.

    Table 12-2. Struts Client-Side Validators

    Validator Name

    Parameters

    Purpose

    required

    none

    Checks that the field has characters other than white space

    maxlength

    maxlength

    Checks that the field length is at most the value of the maxlength parameter

    minlength

    minlength

    Checks that the field length is at least the value of the minlength parameter

    byte

    none

    Checks that the field contains an integer between -128 and 127

    short

    none

    Checks that the field contains an integer between -32768 and 32767

    integer

    none

    Checks that the field contains an integer between -2147483648 and 2147483647

    float

    none

    Checks that the field contains a floating-point number

    intRange

    Min, max

    Checks that the field contains an integer between min and max. Both must be specified.

    floatRange

    Min, max

    Checks that the field contains a floating-point number between min and max. Both must be specified.

    date

    datePatternStrict

    Checks that the field contains a date with the given pattern

    email

    none

    Checks that the field contains a syntactically correct email address

    creditCard

    none

    Checks that the field contains a credit card number that passes the Luhn check

    mask

    mask

    Checks that the field matches the regular expression given in the mask parameter


To demonstrate this technique, we added client-side validators to the validator application of Chapter 6. Figure 12-10 shows a validation error message.

Figure 12-10. Client-Side Validation

graphics/12fig10.jpg


Figure 12-11 shows the directory structure of the application.

Figure 12-11. Directory Structure of the struts-validator Application

graphics/12fig11.jpg


Using the Struts validator is an attractive option if you are already familiar with Struts. However, it is quite a bother to specify the validation rules in an external file that is completely separate from your JSF pages. You can do better than that with a couple of custom tags see the next section.

Listing 12-21. struts-validator/WEB-INF/struts-config.xml
  1. <?xml version="1.0" encoding="ISO-8859-1" ?>  2.  3. <!DOCTYPE struts-config PUBLIC  4.           "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"  5.           "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">  6.  7. <struts-config>  8.  9.    <message-resources parameter="com.corejsf.messages"/> 10.    <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> 11.       <set-property property="pathnames" 12.          value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> 13.    </plug-in> 14. 15. </struts-config> 

Listing 12-22. struts-validator/WEB-INF/classes/com/corejsf/messages.properties
  1. title=An Application to Test Validation  2. enterPayment=Please enter the payment information:  3. amount=Amount:  4. creditCard=Credit Card:  5. expirationDate=Expiration date (Month/Year):  6. paymentInformation=Payment information  7. canceled=The transaction has been canceled.  8. back=Back  9. 10. errors.required={0} is required. 11. errors.minlength={0} can not be less than {1} characters. 12. errors.maxlength={0} can not be greater than {1} characters. 13. errors.invalid={0} is invalid. 14. 15. errors.byte={0} must be a byte. 16. errors.short={0} must be a short. 17. errors.integer={0} must be an integer. 18. errors.long={0} must be a long. 19. errors.float={0} must be a float. 20. errors.double={0} must be a double. 21. 22. errors.date={0} is not a date. 23. errors.range={0} is not in the range {1} through {2}. 24. errors.creditcard={0} is an invalid credit card number. 25. errors.email={0} is an invalid e-mail address. 

Listing 12-23. struts-validator/index.jsp
  1. <html>  2.    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>  3.    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>  4.    <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>  5.  6.    <f:view>  7.       <head>  8.          <link href="styles.css" rel="stylesheet" type="text/css"/>  9.          <f:loadBundle basename="com.corejsf.messages" var="msgs"/> 10.          <html:javascript formName="paymentForm"/> 11.          <title><h:outputText value="#{msgs.title}"/></title> 12.       </head> 13.       <body> 14.          <h:form  onsubmit="return validatePaymentForm(this);"> 15.             <h1><h:outputText value="#{msgs.enterPayment}"/></h1> 16.             <h:panelGrid columns="3"> 17.                <h:outputText value="#{msgs.amount}"/> 18.                <h:inputText  value="#{payment.amount}" 19.                   required="true"> 20.                   <f:convertNumber minFractionDigits="2"/> 21.                   <f:validateDoubleRange minimum="10" maximum="10000"/> 22.                </h:inputText> 23.                <h:message for="amount" style/> 24. 25.                <h:outputText value="#{msgs.creditCard}"/> 26.                <h:inputText  value="#{payment.card}" 27.                   required="true"> 28.                   <f:validateLength minimum="13"/> 29.                </h:inputText> 30.                <h:message for="card" style/> 31. 32.                <h:outputText value="#{msgs.expirationDate}"/> 33.                <h:inputText  value="#{payment.date}" 34.                   required="true"> 35.                   <f:convertDateTime pattern="MM/yyyy"/> 36.                </h:inputText> 37.                <h:message for="date" style/> 38.             </h:panelGrid> 39.             <h:commandButton value="Process" action="process"/> 40.             <h:commandButton value="Cancel" action="cancel" immediate="true"/> 41.          </h:form> 42.       </body> 43.    </f:view> 44. </html> 

Listing 12-24. struts-validator/WEB-INF/validation.xml
  1. <?xml version="1.0" encoding="ISO-8859-1" ?>  2. <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons  3.    Validator Rules Configuration 1.0//EN"  4.    "http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">  5. <form-validation>  6.    <formset>  7.       <form name="paymentForm">  8.          <field property="paymentForm:amount" depends="required">  9.             <arg0 key="amount"/> 10.          </field> 11.          <field property="paymentForm:card" depends="required,minlength"> 12.             <arg0 key="creditCard"/> 13.             <arg1 key="${var:minlength}" resource="false"/> 14.             <var> 15.                <var-name>minlength</var-name> 16.                <var-value>13</var-value> 17.             </var> 18.          </field> 19.          <field property="paymentForm:date" depends="required,date"> 20.             <arg0 key="expirationDate"/> 21.             <var> 22.                <var-name>datePatternStrict</var-name> 23.                <var-value>MM/yyyy</var-value> 24.             </var> 25.          </field> 26.       </form> 27.    </formset> 28. </form-validation> 

How do I write my own client-side validation tag?

Let us suppose you have developed a JavaScript function for validation and tested it on multiple browsers. Now you would like to use it in your JSF applications. You need two tags:

  1. A validator tag that is attached to each component that requires validation.

  2. A component tag that generates the JavaScript code for validating all components on the form. The component tag must be added to the end of the form. Note that we cannot use a validator tag for this purpose. Only components can render output.

As an example, we show you how to make use of the credit card validation code in the Struts Validator (see Listing 12-25 on page 609). We produce two tags: a creditCardValidator tag that can be added to any JSF input component, and a component tag validatorScript that generates the required JavaScript code.

The creditCardValidator tag has two attributes. The message attribute specifies the error message template, such as

 

 {0} is not a valid credit card number 

The arg attribute is the value that should be filled in for {0}, usually the field name. For example,

 

 <corejsf:creditCardValidator    message="#{msgs.invalidCard}" arg="#{msgs.primaryCard}"/> 

The code for the validator is in Listing 12-26 on page 610. The validator class has two unrelated purposes: validation and error message formatting.

The class carries out a traditional server-side validation, independent of the client-side JavaScript code. After all, it is not a good idea to solely rely on client-side validation. Users may have deactivated JavaScript in their browsers. Also, automated scripts or web-savvy hackers may send unvalidated HTTP requests to your web application.

The getErrorMessage method formats an error message that will be included in the client-side JavaScript code. The error message is constructed from the message and arg attributes.

The validatorScript component is far more interesting see Listing 12-27 on page 612. Its encodeBegin method calls the recursive findCreditCardValidators method, which walks the component tree, locates all components, enumerates their validators, checks which ones are credit card validators, and gathers them in a map object. The writeValidationFunctions method writes the JavaScript code that invokes the validation function on all fields with credit card validators.

You must place the validatorScript tag at the end of the form, like this:

 

 <h:form  onsubmit="return validatePaymentForm(this);">    ...    <corejsf:validatorScript functionName="validatePaymentForm"/> </h:form> 

Listing 12-28 on page 614 shows a sample JSF page.

CAUTION

graphics/caution_icon.gif

If you place the validatorScript tag before the tags for the components that need to be validated, then the code that traverses the form component may not find the validators! This unintuitive and annoying behavior is a consequence of the JSP mechanism on which the JSF reference implementation is based. When a JSP-based implementation renders a JSF page for the first time, the component tree does not yet exist. Instead, it intermingles rendering and construction of the component tree.


The details of the writeValidationFunctions depend on the intricacies of the JavaScript code used by the Struts validator, which is taken from the Commons Validator project see http://jakarta.apache.org/commons/validator.

NOTE

graphics/note_icon.gif

As we write this book, the JavaScript functions are not a part of the source or binary distribution of the Commons Validator project. You can get them from CVS at http://cvs.apache.org/viewcvs.cgi/jakarta-commons/validator/src/javascript. The development of this library is still in flux you may need to tweak our code to match later versions.


First, the writeValidationFunctions method produces the validation function that is called in the onsubmit handler of the form:

 

 var bCancel = false; function functionName(form) { return bCancel || validateCreditCard(form); } 

If a form contains "Cancel" or "Back" buttons, their onclick handlers should set the bCancel variable to true, in order to bypass validation.

The validateCreditCard function is the entry point into the Commons Validator code. It expects to find a function named creditCard that constructs a configuration object. The writeValidationFunctions method generates the code for the creditCard function.

Unfortunately, the details are rather convoluted. The creditCard function returns an object with one instance field for each validated form element. Each instance field contains an array with two values: the ID of the form element and the error message to display when validation fails. The instance field names don't matter. In the writeValidationFunctions method, we take advantage of the flexibility of JavaScript and simply call the fields 0, 1, 2, and so on. For example,

 

 function creditCard() {    this[0] = new Array("paymentForm:primary",       "Primary Credit Card is not a valid card number");    this[1] = new Array("paymentForm:backup",       "Backup Credit Card is not a valid card number"); } 

If you design your own JavaScript functions, you can provide a saner mechanism for bundling up the parameters.

Listing 12-25. clientside-validator/scripts/validateCreditCard.js
  1.     /*$RCSfile: validateCreditCard.js,v $ $Revision: 1.5 $ $Date: 2003/12/15 02:56:57 $ */  2.     /**  3.     * Check to see if fields are a valid creditcard number based on Luhn checksum.  4.     * Fields are not checked if they are disabled.  5.     * <p>  6.     * @param form The form validation is taking place on.  7.     */  8.     function validateCreditCard(form) {  9.         var bValid = true; 10.         var focusField = null; 11.         var i = 0; 12.         var fields = new Array(); 13.         oCreditCard = new creditCard(); 14.         for (x in oCreditCard) { 15.             if ((form[oCreditCard[x][0]].type == 'text' || 16.                  form[oCreditCard[x][0]].type == 'textarea') && 17.                 (form[oCreditCard[x][0]].value.length > 0)  && 18.                  form[oCreditCard[x][0]].disabled == false) { 19.                 if (!luhnCheck(form[oCreditCard[x][0]].value)) { 20.                     if (i == 0) { 21.                         focusField = form[oCreditCard[x][0]]; 22.                     } 23.                     fields[i++] = oCreditCard[x][1]; 24.                     bValid = false; 25.                 } 26.             } 27.         } 28.         if (fields.length > 0) { 29.             focusField.focus(); 30.             alert(fields.join('\n')); 31.         } 32.         return bValid; 33.     } 34. 35.     /** 36.      * Checks whether a given credit card number has a valid Luhn checksum. 37.      * This allows you to spot most randomly made-up or garbled credit card 38.      * numbers immediately. 39.      * Reference: http://www.speech.cs.cmu.edu/~sburke/pub/luhn_lib.html 40.      */ 41.     function luhnCheck(cardNumber) { 42.         if (isLuhnNum(cardNumber)) { 43.             var no_digit = cardNumber.length; 44.             var oddoeven = no_digit & 1; 45.             var sum = 0; 46.             for (var count = 0; count < no_digit; count++) { 47.                 var digit = parseInt(cardNumber.charAt(count)); 48.                 if (!((count & 1) ^ oddoeven)) { 49.                     digit *= 2; 50.                     if (digit > 9) digit -= 9; 51.                 }; 52.                 sum += digit; 53.             }; 54.             if (sum == 0) return false; 55.             if (sum % 10 == 0) return true; 56.         }; 57.         return false; 58.     } 59. 60.     function isLuhnNum(argvalue) { 61.         argvalue = argvalue.toString(); 62.         if (argvalue.length == 0) { 63.             return false; 64.         } 65.         for (var n = 0; n < argvalue.length; n++) { 66.             if ((argvalue.substring(n, n+1) < "0") || 67.                 (argvalue.substring(n,n+1) > "9")) { 68.                 return false; 69.             } 70.         } 71.         return true; 72.     } 

Listing 12-26. clientside-validator/WEB-INF/classes/com/corejsf/CreditCardValidator.java
  1. package com.corejsf;  2.  3. import java.io.Serializable;  4. import java.text.MessageFormat;  5. import java.util.Locale;  6. import javax.faces.application.FacesMessage;  7. import javax.faces.component.UIComponent;  8. import javax.faces.context.FacesContext;  9. import javax.faces.validator.Validator; 10. import javax.faces.validator.ValidatorException; 11. 12. public class CreditCardValidator implements Validator, Serializable { 13.    private String message; 14.    private String arg; 15. 16.    // PROPERTY: message 17.    public void setMessage(String newValue) { message = newValue; } 18. 19.    // PROPERTY: arg 20.    public void setArg(String newValue) { arg = newValue; } 21.    public String getArg() { return arg; } 22. 23.    public void validate(FacesContext context, UIComponent component, 24.       Object value) { 25.       if(value == null) return; 26.       String cardNumber; 27.       if (value instanceof CreditCard) 28.          cardNumber = value.toString(); 29.       else 30.          cardNumber = getDigitsOnly(value.toString()); 31.       if(!luhnCheck(cardNumber)) { 32.          FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, 33.             getErrorMessage(value, context), null); 34.          throw new ValidatorException(message); 35.       } 36.    } 37. 38.    public String getErrorMessage(Object value, FacesContext context) { 39.       Object[] params = new Object[] { value }; 40.       if (message == null) 41.          return com.corejsf.util.Messages.getString( 42.                "com.corejsf.messages", "badLuhnCheck", params); 43.       else { 44.          Locale locale = context.getViewRoot().getLocale(); 45.          MessageFormat formatter = new MessageFormat(message, locale); 46.          return formatter.format(params); 47.       } 48.    } 49. 50.    private static boolean luhnCheck(String cardNumber) { 51.       int sum = 0; 52. 53.       for(int i = cardNumber.length() - 1; i >= 0; i -= 2) { 54.          sum += Integer.parseInt(cardNumber.substring(i, i + 1)); 55.          if(i > 0) { 56.             int d = 2 * Integer.parseInt(cardNumber.substring(i - 1, i)); 57.             if(d > 9) d -= 9; 58.             sum += d; 59.          } 60.       } 1. 62.       return sum % 10 == 0; 63.    } 64. 65.    private static String getDigitsOnly(String s) { 66.       StringBuffer digitsOnly = new StringBuffer (); 67.       char c; 68.       for(int i = 0; i < s.length (); i++) { 69.          c = s.charAt (i); 70.          if (Character.isDigit(c)) { 71.             digitsOnly.append(c); 72.          } 73.       } 74.       return digitsOnly.toString (); 75.    } 76. } 

Listing 12-27. clientside-validator/WEB-INF/classes/com/corejsf/UIValidatorScript.java
  1. package com.corejsf;  2.  3. import java.io.IOException;  4. import java.util.Iterator;  5. import java.util.List;  6. import java.util.Map;  7. import java.util.TreeMap;  8. import javax.faces.component.EditableValueHolder;  9. import javax.faces.component.UIComponent; 10. import javax.faces.component.UIComponentBase; 11. import javax.faces.context.FacesContext; 12. import javax.faces.context.ResponseWriter; 13. import javax.faces.validator.Validator; 14. 15. public class UIValidatorScript extends UIComponentBase { 16.    private Map validators = new TreeMap(); 17.    // a map from IDs to CreditCardValidator objects 18. 19.    public String getRendererType() { return null; } 20.    public String getFamily() { return null; } 21. 22.    private void findCreditCardValidators(UIComponent c, FacesContext context) { 23.       if (c instanceof EditableValueHolder) { 24.          EditableValueHolder h = (EditableValueHolder) c; 25.          Validator[] vs = h.getValidators(); 26.          for (int i = 0; i < vs.length; i++) { 27.             if (vs[i] instanceof CreditCardValidator) { 28.                CreditCardValidator v = (CreditCardValidator) vs[i]; 29.                String id = c.getClientId(context); 30.                validators.put(id, v); 31.             } 32.          } 33.       } 34. 35.       List children = c.getChildren(); 36.       for (int i = 0; i < children.size(); i++) { 37.          UIComponent child = (UIComponent) children.get(i); 38.          findCreditCardValidators(child, context); 39.       } 40.    } 41. 42.    private void writeScriptStart(ResponseWriter writer) throws IOException { 43.       writer.startElement("script", this); 44.       writer.writeAttribute("type", "text/javascript", null); 45.       writer.writeAttribute("language", "Javascript1.1", null); 46.       writer.write("\n<!--\n"); 47.     } 48. 49.    private void writeScriptEnd(ResponseWriter writer) throws IOException { 50.       writer.write("\n-->\n"); 51.       writer.endElement("script"); 52.    } 53. 54.    private void writeValidationFunctions(ResponseWriter writer, 55.       FacesContext context) throws IOException { 56.       writer.write("var bCancel = false;\n"); 57.       writer.write("function " ); 58.       writer.write(getAttributes().get("functionName").toString()); 59.       writer.write("(form) { return bCancel || validateCreditCard(form); }\n"); 60. 61.       writer.write("function creditCard() { \n"); 62.       // for each field validated by this type, add configuration object 63.       Iterator iter = validators.keySet().iterator(); 64.       int k = 0; 65.       while (iter.hasNext()) { 66.          String id = (String) iter.next(); 67.          CreditCardValidator v = (CreditCardValidator) validators.get(id); 68.          writer.write("this[" + k + "] = "); 69.          k++; 70. 71.          writer.write("new Array('"); 72.          writer.write(id); 73.          writer.write("', '"); 74.          writer.write(v.getErrorMessage(v.getArg(), context)); 75.          writer.write("');\n");; 76.       } 77.       writer.write("}\n"); 78.    } 79. 80.    public void encodeBegin(FacesContext context) throws IOException { 81.       String id = getClientId(context); 82.       ResponseWriter writer = context.getResponseWriter(); 83. 84.       validators.clear(); 85.       findCreditCardValidators(context.getViewRoot(), context); 86. 87.       writeScriptStart(writer); 88.       writeValidationFunctions(writer, context); 89.       writeScriptEnd(writer); 90.    } 91. } 

Listing 12-28. clientside-validator/index.jsp
  1. <html>  2.    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>  3.    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>  4.    <%@ taglib uri="http://corejsf.com/creditcard" prefix="corejsf" %>  5.    <f:view>  6.       <head>  7.          <link href="styles.css" rel="stylesheet" type="text/css"/>  8.          <f:loadBundle basename="com.corejsf.messages" var="msgs"/>  9. 10.          <script src="/books/2/113/1/html/2/scripts/validateCreditCard.js" 11.             type="text/javascript" language="JavaScript1.1"> 12.          </script> 13.          <title><h:outputText value="#{msgs.title}"/></title> 14.       </head> 15.       <body> 16.          <h:form  onsubmit="return validatePaymentForm(this);"> 17.             <h1><h:outputText value="#{msgs.enterPayment}"/></h1> 18.             <h:panelGrid columns="3"> 19.                <h:outputText value="#{msgs.amount}"/> 20.                <h:inputText  value="#{payment.amount}"> 21.                   <f:convertNumber minFractionDigits="2"/> 22.                </h:inputText> 23.                <h:message for="amount" style/> 24. 25.                <h:outputText value="#{msgs.creditCard}"/> 26.                <h:inputText  value="#{payment.card}" required="true"> 27.                   <corejsf:creditCardValidator 28.                      message="#{msgs.unknownType}"arg="#{msgs.creditCard}"/> 29.                </h:inputText> 30.                <h:message for="card" style/> 31. 32.                <h:outputText value="#{msgs.expirationDate}"/> 33.                <h:inputText  value="#{payment.date}"> 34.                   <f:convertDateTime pattern="MM/dd/yyyy"/> 35.                </h:inputText> 36.                <h:message for="date" style/> 37.             </h:panelGrid> 38.             <h:commandButton value="Process" action="process"/> 39.             <corejsf:validatorScript functionName="validatePaymentForm"/> 40.          </h:form> 41.       </body> 42.    </f:view> 43. </html> 

How do I use the Jakarta Commons Validator for client-side validation?

In the preceding section, you saw how to write your own validator tag that puts a validation script from the Commons Validator project to work. If you like that approach, there is no need to get busy and replicate that work for all of the other validators. We supply a custom tag library for this purpose.

To use our wrapper around Commons Validator, follow these instructions:

  1. Place the library file corejsf-validator.jar into the WEB-INF/lib directory of your web application. Place the file validation-rules.xml into the WEB-INF/lib directory of your web application. Both files are included in the companion code for this book.

  2. Place the library files commons-validator.jar and jakarta-oro.jar into the WEB-INF/lib directory of your web application. The files are available at http://jakarta.apache.org/commons/validator and http://jakarta.apache.org/oro.

  3. Include a tag library declaration such as

     

     <%@ taglib uri="http://corejsf.com/validator" prefix="v" %> 

    Here, we use v as a prefix. As always, you can use any prefix of your choice.

  4. Include a call to the validation method in the onsubmit handler of your form, like this:

     

     <h:form  onsubmit="return validatePaymentForm(this);"> 

    Just before the </h:form> tag, add a v:validatorScript tag:

     

     <v:validatorScript functionName="validatePaymentForm"/> 

    The function name must match the function in the onsubmit handler.

  5. Add validators to your components, for example:

     

     <h:inputText  value="#{payment.amount}">    <v:commonsValidator type="floatRange"       min="10" max="10000" arg="#{msgs.amount}"/> </h:inputText> 

    The type argument is the validator type. It should be one of the types of Table 12-2. Supply attributes min, max, minlength, maxlength, mask, and datePatternStrict as required by the validation method that you choose. Supply the argument for the error message in the arg attribute. Typically, this is the name of the field.

How do I validate relationships between components?

In JSF, validators are intended to check the validity of a single component. However, you often need to test relationships between components. For example, it is common to ask users to reenter a password. You'd like to show a validation error if the two passwords are not identical.

The sophisticated approach is to design a custom component that renders two input fields, one for the password and one for the confirmed password. That is quite elegant, but of course it is a lot of work.

The other approach is simply to let the last of the related components do the validation. The preceding components will have their local values set, and your validator code can read them. For the last component only, you need to use the value that was passed by the validation method.

The validation method is most conveniently placed in a backing bean that also holds the components of the form. For example,

 

 public class BackingBean {    private UIInput passwordField;    private UIInput confirmField;    ...    public void validateConfirmField(FacesContext context, UIComponent component,       Object value) {       if (!passwordField.getLocalValue().equals(value))          throw new ValidatorException(...); } 

You then simply attach the validator to the confirmation field:

 

 <h:inputText binding="#{bb.confirmField}" required="true"    validator="#{bb.validateConfirmField}"/> 

For a more complete example of this technique, see Chapter 6.



core JavaServer Faces
Core JavaServer Faces
ISBN: 0131463055
EAN: 2147483647
Year: 2003
Pages: 121

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net