CSValidation: A TextField with client-side validation with regexps and JS

I know some others have done client-side validation of text fields as well, but I haven’t seen anything published in the Incubator. It wasn’t too hard to do, so here it is.

The
CSValidationTextField
(suggestions for a better name are welcome) is an extension of the regular
TextField
. It can validate the input with a regular expression and/or a JavaScript program.

Of course, you can’t trust the client-side code for validation,so you need to validate the input on the server-side as well. For regular expression validation, you can use the same expression for the server-side
RegexpValidator
. For example:

// The Finnish Social Security Number
final CSValidatedTextField ssn = new CSValidatedTextField("SSN");
String ssn_regexp = "[0-9]
{6}[+-A]
[0-9]
{3}[0-9a-zA-Z]
"; 

// The client-side validation
ssn.setRegExp(ssn_regexp, "000000-000A");
ssn.setAllowInvalid(false); // Prevent typing invalid values

// The server-side validation
ssn.addValidator(new RegexpValidator(ssn_regexp, "Invalid SSN"));
ssn.setRequired(true);
ssn.setRequiredError("SSN is required");

form.addField("ssn", ssn);

Matching partially filled values has some problems currently. If you disallow typing invalid input, as in the example above, the regexp validation currently needs an “example” and is restricted to only fixed-length fields. I’ll have to look if the JS regexp matching can somehow report if there’s a partial match. If you allow invalid input, there are no restrictions and the fixed-length example is not needed.

You can validate with JavaScript just as easily:

CSValidatedTextField postcode = new CSValidatedTextField("Postal Code");
postcode.setJavaScript("if (value >= 0 && value < 10000)" +
                       "    \"partial\";" +
                       "else if (value >= 10000 && value <= 99999)" +
                       "    null;" +
                       "else" +
                       "    \"Postal Code must be a 5-digit number between 10000 and 99999\";");
layout.addComponent(postcode);

The server-side validation needs separate Java code though, unless you use some JavaScript execution library.

You just
need
to validate the input on the server-side as well, as the client-side validation does not actually prevent inputting invalid values (unless you set setAllowInvalid(false), but that’s a bit restricted at the moment).

Password input is handled with a separate
CSValidatedPasswordField
and multi-row text input with
CSValidatedTextArea
.

See the example source codes (link below) for more examples.

See:

[list]

[]

The Demo (editors, some validation examples)

[
]

API Documentation

[]

Source Repository

[
]

Example Souce Code

[/list]Included are also handy interactive editors for the regular expressions and JavaScript validators, as you can see in the demos.


Update 15.4.2011:
Changed the thread title and mentioned -TextArea and -PasswordField.

Now there’s also an installation JAR for Vaadin 6.2. As 6.2 is not yet there, you’ll need a Vaadin nightly Jar.

Download [tt]
csvalidation.jar
[/tt] from the
demo page
.

The installation is quite simple, just drop the Jar in your lib folder and set your app to use the Jar in the [tt]
web.xml
[/tt], as instructed in the above page.

As a word of warning: GWT evaluates the regular expression on the client side using the JavaScript regexp syntax, which differs slightly from the Java syntax used on the server side. When using complex regular expressions for both server and client side validation, check that they are compatible with both to avoid surprises.

CSValidationTextField doesn’t work with CssLayouts, where all the components have the same parent, and not only the validation text field and the error message, so the validation removes one of the other components from the layout each time it tries to modify or remove the error message.

I haven’t extensively tested it, so I can’t guarantee it doesn’t break something else, but these changes did the job for me:


         Element textbox = DOM.getParent(getElement());
         Element span = DOM.getNextSibling(getElement());
+		String elementClass = DOM.getElementAttribute(span, "class");
+		if (!(elementClass.contains("v-validatedtextfield-validmessage")
+				|| elementClass.contains("v-validatedtextfield-partialmessage")
+				|| elementClass.contains("v-validatedtextfield-errormessage"))
+			span = null;
         if (span == null && message != null) {
             span = DOM.createSpan();
-            DOM.appendChild(textbox, span);
+			DOM.insertChild(textbox, span, DOM.getChildIndex(textbox, getElement()) + 1);
             span.setInnerText(message);
         } else if (span != null && message != null) {

Hi,

Thanks for the patch! :wink:

The added part probably needs to be enclosed in “if (span != null) {…}”.

I’ll add it to the add-on soon.

Hi,

i noticed that when you have a regular expression like [0-9]

*
you have to enter at least one digit to get a valid input, although the * means that you are allowed to enter zero characters. Is there a way to allow removing all of the entered characters, perhaps by ignoring null values or empty strings?

Thanks and best regards!

Ralf

Hi,

Yes, that’s a known issue that was noticed just recently, have to fix it. Meanwhile, see
this post for a workaround
.

It’s been a long time since the latest release, so I made the recently suggested fixes and pushed out a new version.
Get it
from the Directory.

Changes:

[list]

[]
Changed package name from [tt]
com.vaadin.csvalidation
[/tt] to [tt]
org.vaadin.csvalidation
[/tt] to follow the naming policy for non-official and community add-ons.
[
]
Validate also empty values with regular expressions (support for example [tt]
[0-9]
*
[/tt]), unless disabled with [tt]
setValidateEmptyValue(false)
[/tt].
[*]
Applied the patch to fix the problem with possible span elements after the component, for example in CssLayout. Did not verify that the fix works, so please tell me if it doesn’t.

[/list]Compiled with Vaadin 6.5.4 and GWT 2.1.1, but could work with earlier versions as well.

Tested with Firefox 4 and Chrome 4, and I assume that other versions work as well. I have never tested with IE, but I suppose it works as well as nobody has complained about it. Complain if it doesn’t.

Updated also
the Demo
. Demonstrates also the use of [tt]
[0-9]
*
[/tt] regexp.

This old but valid thread belongs to the Add-ons category that was created at some point.


Update:
Uhh, failed to move it… :open_mouth: …and succeeded.

Release notes says that in the latest version the package name has been changed but when I download the latest jar it still has the old package structure.

"0.4.0:
Changed package name from com.vaadin.csvalidation to org.vaadin.csvalidation
"

The Manifest.mf show the following entry

Vaadin-Widgetsets: org.vaadin.csvalidation.widgetset.CSValidationWidgetset

Exception -

Loading inherited module ‘org.vaadin.csvalidation.widgetset.CSValidationWidgetset’
[ERROR]
Unable to find ‘org/vaadin/csvalidation/widgetset/CSValidationWidgetset.gwt.xml’ on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?
[ERROR]
Line 54: Unexpected exception while processing element ‘inherits’
com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)
at com.google.gwt.dev.cfg.ModuleDefLoader.nestedLoad(ModuleDefLoader.java:248)
at com.google.gwt.dev.cfg.ModuleDefSchema$BodySchema.__inherits_begin(ModuleDefSchema.java:413)

Please advice? Am I looking at wrong file or wrong location?

The JAR was missing files because of the com->org change. I should have tested the Jar before release, but oh well… Sorry about that.

Fixed version 0.4.1
is now available
.

Thanks for reporting this.

Thanks Marko.

You also have to add a server side Validator in order to prevent form commit right?
I mean there is yet no way of knowing if the field is validated or not on client-side.

That’s right, the client-side validation is merely visual and does not prevent committing invalid content in any way. Even with “preventInvalidTyping”, a malicious client could hack the client-side validation and submit invalid data.

The version 0.5.0 of the
CSValidation add-on
is now available. It’s for Vaadin 7 and comes as a
CSValidator
component extension for
TextField
,
PasswordField
, and
TextArea
. Extensions are attached to components with [tt]
extension.extend(component)
[/tt].

For example:

// A regular text field (no more CSValidatedTextField)
final TextField postcode = new TextField("Postal Code");

// Create the component extension and attach it to the component
final CSValidator validator = new CSValidator();
validator.extend(postcode);
validator.setJavaScript("if (value >= 0 && value < 10000)" +
    "    \"partial\";" +
    "else if (value >= 10000 && value <= 99999)" +
    "    null;" +
    "else" +
    "    \"Postal Code must be a 5-digit number between 10000 and 99999\";");

Otherwise, the functionality is exactly same as before. For Vaadin 6, you should keep using the version 0.4.x.

The
demo
is also updated.

Does csvalidation 4.1 work with vaadin 6.8.4. I included

<dependency>
   <groupId>org.vaadin.addons</groupId>
   <artifactId>csvalidation</artifactId>
   <version>0.4.1</version>
</dependency>

<repository>
   <id>vaadin-addons</id>
   <url>http://maven.vaadin.com/vaadin-addons</url>
</repository>

in pom.xml

However I don’t see any compile errors when I use


private CSValidatedTextField appKey = appKey = new CSValidatedTextField("Application Key:");	
appKey.setRegExp("[A-Z]
");

but when I open the form which has this field I see error as seen in screenshot
12848.jpg

You have not compiled the widget set properly. It’s hard to say what your problem could be. See the
relevant book section
for using the add-ons with Maven.

How can I get validation result of field? I mean failed\passed.

goalValidator = new CSValidator();
goalValidator.setRegExp(“[a-zA-ZА-Яа-я0-9!?,."]
{1,200}”);
goalValidator.extend(goalTextArea);

Just to inform you: Your demo is currently down because of an OutofMemoryException:

java.lang.OutOfMemoryError: PermGen space

Thanks for noting, I hadn’t noticed that. This isn’t the first time, so I suppose I should put up a watchdog there…

Thanks.