Best JavaScript solution for client-side form validation and interaction? [closed]

This is a shameless plug, but might I volunteer a framework that I designed? I’ve built it based on annotations (a la Hibernate Validator). It has support for custom constraints and I feel that it is pretty powerful. Here is also a Stackoverflow question where I asked for a review of the framework.

  • Presentation: With custom validation-constraints, you can bind validation to the onChange element. Also, because Regula supports custom validators, you can have your custom validator update the value of a field (so change 5 to 5.00).
  • Side effects: Regula supports side-effects via custom constraint-validators.
  • Groups: Regula supports validation groups. You can target specific groups for validation. By combining a custom validator and a group, you can control the behavior of the validator so that it validates only when all elements of that group are filled (you would have to perform this check via normal Javascript though).
  • Server-side validation: With custom-constraints, you can make an AJAX call to perform server-side validation. With the way the framework is structured currently, this necessarily has to be a blocking ajax-call. I plan on adding an asynchronous feature in the future.
  • Multiplee forms per page: Regula isn’t limited to validating one form per page. It can handle multiple forms (not sure if I understood your requirement correctly – so I might not have answered this part correctly).
  • Customizable error display: Regula doesn’t do anything to the UI of the page as far as validation is concerned. When you validate, you get a set of constraint violations that contain error messages and such. It is up to you, how to display them.
  • Snappiness: I haven’t performed any benchmarks, so I cannot comment as to my framework’s performance in this regard.
  • Submit buttons: This is something I have yet to solve (asynchronous vs. synchronous).

Here are a few examples:

The following shows standard validation, with built-in constraints:

<input id = "myInput"
       name = "myInput"
       type = "text"
       class = "regula-validation"
       data-constraints="@NotEmpty @IsNumeric @Between(min=1, max=5)" />

jQuery(document).ready(function() {
    // must call regula.binnd() first. The best place would be in an
    // onload handler. This function looks for elements with
    // a class name of "regula-validation" and binds the
    // appropriate constraints to the elements

    regula.bind(); 

    jQuery("#myForm").submit(function() {
        // this function performs the actual validation
        var validationResults = regula.validate();

        for(var index in validationResults) {
             var validationResult = validationResults[index];
             alert(validationResult.message);
        }
    });
});

As you can see, you’re only working with constraint violations, and so the manner in which you display the error message is entirely up to you.

Here’s an example of a custom constraint:

regula.custom({
   name: "MustBe42",
   defaultMessage: "The answer must be equal to 42",
   validator: function() {
      return this.value == 42;
   }
});

And its use:

<input id = "theAnswerToLifeTheUniverseAndEverything" 
       name = "theAnswerToLifeTheUniverseAndEverything" 
       value = ""
       class = "regula-validation"
       data-constraints = "@MustBe42" />

Since the validator is a Javascript function, you can have it do anything (so this addresses your question about side effects).

Here is an example of another constraint that accepts parameters:

regula.custom({
   name: "DivisibleBy",
   defaultMessage: "{label} must be divisible by {divisor}",
   params: ["divisor"],
   validator: function(params) {
      var divisor = params["divisor"];
      return (this.value % divisor) == 0;
   }
});

And usage:

<input id = "number" 
       name = "number" 
       value = ""
       class = "regula-validation"
       data-constraints = "@DivisibleBy(divisor=3, label="The Number")" />

Here is an example of using validation groups:

<input id = "score"
       name = "score"
       type = "text"
       class = "regula-validation"
       data-constraints="@IsNumeric(label="Score", 
                                      message="{label} needs to be a number!"
                                      groups=[FirstGroup, SecondGroup, ThirdGroup]" />

<input id = "age"
       name = "age"
       type = "text"
       class = "regula-validation"
       data-constraints="@IsNumeric(label="Age", 
                                      message="{label} needs to be a number!"
                                      groups=[SecondGroup]" />

<input id = "name"
       name = "name"
       type = "text"
       class = "regula-validation"
       data-constraints="@NotEmpty(label="Name", 
                                     message="{label} cannot be empty!"
                                     groups=[FirstGroup]" />

And a snippet that validates only FirstGroup (so only score and name are validated):

var constraintViolations = regula.validate({groups: [regula.Group.FirstGroup]});
var messages = "";

for(var index in constraintViolations) {
      var constraintViolation = constraintViolations[index];
      messages += constraintViolation.message + "\n";
}

if(messages != "") {
   alert(messages);
}

If you’re planning on trying it out, I recommend downloading version 1.1.1. The current documentation matches that version specifically. In 1.2.1 I added support for compound constraints, but I haven’t updated my documentation to reflect that.

I understand if this doesn’t address all your concerns, or if this is not what you are looking for. I thought I’d just put it out there. Also, if you do check it out then I will make sure to update the documentation to reflect version 1.2.1. I’ve been busy with school and work and so I haven’t had the time to do that.

UPDATE #1

Sohnee mentioned client-side validation. I’m actually working on an integration between Regula and Spring 3. Hopefully I should be able to release it sometime soon (depending again, on work and school). The integration works by translating Hibernate validation-constraints to Regula validation-constraints. This way, you only have to write validation code once (mostly). For custom constraints though, you will still have to write code on the Javascript side (the custom validator). But once you annotate code on the server-side with Hibernate validation-constraints, you don’t need to do anything on the client-side; those constraints automatically get applied to form elements on the client-side.

Matthew Abbott has also been able to integrate Regula with ASP.NET MVC.

UPDATE #2

I’ve got a demo webapp (mavenized) on github that showcases the integration between Regula and Spring 3.0.x Web MVC using Hibernate Validator. It’s not really documented or anything, it’s more proof-of-concept. I plan to add some documentation to the github page about the integration and how it works.

UPDATE #3

I’ve updated the documentation on the wiki, and it now corresponds to the latest version, 1.2.2 (I made a little bugfix, which is why it is 1.2.2 now).

Leave a Comment