IBM®
Skip to main content
    Country/region select      Terms of use
 
 
   
     Home      Products      Services & solutions      Support & downloads      My account     

developerWorks  >  Lotus  >  Forums & community  >  Best Practice Makes Perfect

Best Practice Makes Perfect

A collaboration with Domino developers about how to do it and how to get it right in Domino

I've been doing some XPages development recently, and I was frustrated by some inconvenience in doing server-side validation using JavaScript.

The typical way of doing a series of validations on the same field, is to have a message and condition for each test, e.g.:

<xp:inputText id="inputText1">
     
<xp:this.validators>
             
<xp:validateRequired
                     
message="This here is a required field.">
             
</xp:validateRequired>
             
<xp:validateExpression
                     
message="The item must be at least 3 characters">
                     
<xp:this.expression><![CDATA[#{javascript:(value.trim().length >= 3)}]]></xp:this.expression>
             
</xp:validateExpression>
             
<xp:validateExpression
                     
message="RTC must be followed by four digits.">
                     
<xp:this.expression>
                     
var valu:string = value.trim();
                      var exp = new RegExp("^rtc[0-9]{4}$", "i");

                      return (!valu.startsWithIgnoreCase("rtc")

                              || valu.match(exp)

                       );
}]]></xp:this.expression>
             
</xp:validateExpression>
     
</xp:this.validators>
...

If the validation might result in multiple mesages, you have to split it up according to which message you want to display, and often end up repeating some work with each condition (such as trimming the string in this case, or testing some other fields to see whether there are some restrictions on this one). You can't put all the validation code into one tidy little subroutine in a server JavaScript library.

Of course, you could have one piece of code that returns true or false and also assigns a viewScope variable that would be read by a computed message element, but that's a little kludgy.
I found the
customValidator element, and the linked article is nice if you want to do validations in Java. But I preferred to add the code to an existing JavaScript library. Fortunately for me, I have access to the people who designed this stuff, so I asked them how to do it and they told me about a couple of system functions I never found in my searching! So, you can start with the following code which includes those calls:

function postValidationError(control, msg) {
     
// msg is the error message string; control is the component being validated
     
// ('this' from the caller).
     
if ((typeof msg) != "string")
             
return;
     
var msgObj = new javax.faces.application.FacesMessage(
              javax.faces.application.FacesMessage.SEVERITY_ERROR, msg, msg

      );

     
facesContext.addMessage(control.getClientId(facesContext), msgObj);
      control.setValid(
false);
}

Put that in your JavaScript library, then write multiple tests in a single piece of JavaScript code, such as:

...<xp:this.validators><xp:customValidator>
     
<xp:this.validate><![CDATA[#{javascript:
var val = value.trim();

if (val.length < 3)

      postValidationError(this,
"The item must be at least 3 characters");
else if (valu.startsWithIgnoreCase("rtc")) {

      var exp = new RegExp("^rtc[0-9]{4}$", "i");

      if (!val.match(exp)) {

              postValidationError(this,
"RTC must be followed by four digits.");
      }

}

}]]>
</xp:this.validate></xp:customValidator>...

To make things a little simpler, the postValidationError checks the datatype of the msg argument, so you can write a validation function that returns null when valid (or true or any non-string), or the message if not valid. Then you can call postValidationError unconditionally with this return value, and it'll do something appropriate. Note that for a custom validator, the return value is ignored; if you don't do anything to flag the control as invalid, it's assumed to be valid.

Andre Guirard | 4 January 2011 10:36:26 AM ET | Home, Plymouth, MN, USA | Comments (2)

Search this blog 

Disclaimer 

    About IBM Privacy Contact