1

At work we have a web application that is pretty old. So we have a hodge-podge of form-validation solutions. There is a lot of duplicated validation logic, a lot of custom validation logic, some stuff that has been implemented with jQuery validation, some stuff from the bassistance.de validator, and some of the new code even has HTML validation, etc. You get the picture.

We're doing a huge cleanup and refactor on the client side and my task is to figure out ONE WAY to do all the validation. Initially I was going to go with one of the solutions we are already using like jQuery validation, or the bassistance validation plugin. But then I was looking at HTML5 validation and I really like how you can tell from looking at the element what validation rules apply to it. So I decided to go this route. But then I realized that for custom validation, I kind of still have to write them out in Javascript and then there is no easy way to tell if that custom validation rule applies to the element. Basically, I want to do something like this:

<input type="text" required="true" customValidationRule="true" />

Or something like that. But it gets more complicated than that. Some of our custom validation rules require certain parameters and it would be awesome if I could do something like this:

<input type="text" required="true" customValidationRule="true" customValidationRuleParamOne="5" customValidationRuleParamTwo="6" />

I also want to validate certain things as groups, like a person's address details, or credit card details, or things like that. For example, it would be useful to do something like this:

<input type="text" name="street" required="true" group="addressGroup" />
<input type="text" name="city" required="true" group="addressGroup" />
<input type="text" name="state" required="true" group="addressGroup" />
<input type="text" name="zip" required="true" group="addressGroup" />

Then I can just validate everything in "addressGroup" and it would automatically validate all those elements.

To make things more complicated, we also have server-side validation that we do using JSR-303. We currently make AJAX calls for this but I would like to somehow attach that to the element as well using an attribute like asyncValidationRule="true" or something. Can you do something like that in HTML5?

I understand if I am asking for too much. But is there a validation library that has at least some of these features? What I am going for most is the ability to specify validation rules on the element itself. It is ok if it doesn't have any of the other requirements. I can work around that somehow.

Dirty Randy
  • 35
  • 1
  • 4
  • 1
    The jQuery validation plugin does actually let you use data attributes to specify rules, kind of like what you're talking about, see here for more: http://stackoverflow.com/a/15717811/1546831 – Adrien Delessert Jul 11 '13 at 17:04
  • That is great! Can I make validation groups and such? Also, how do I make a custom rule? – Dirty Randy Jul 11 '13 at 17:07
  • I'm not sure, I'm having trouble finding more information about it. I did notice, though, that it also supports remote validation, which is another thing you were looking for: http://validation.bassistance.de/remote-method/ – Adrien Delessert Jul 11 '13 at 17:11
  • Thank you Adrian! I will take a look at it some more. I don't want to deal with bassistance too much because sometimes it is painful and most of the people I work with don't like it very much either. :p – Dirty Randy Jul 11 '13 at 17:31

3 Answers3

2

Disclaimer: I have a horse in this race; I'm the author of the following library.

I've answered a similar question previously that you might want to check out. I'd like to suggest a framework that I've designed called Regula. It does most of what you're asking. Validation rules (or constraints) can be attached directly on the element using the data-constraints attribute.

For example, you can do something like this:

<input type="text" name="something" data-constraints='@Required' />

You can even set things like the error message or labels:

<input type="text" name="something" data-constraints='@Required(label="something" message="{label} is required.")' />

Custom validation is also easy. You do need to define a validator in JavaScript once, but then you can use it after that:

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

And then:

<input type="text" name="something" data-constraints='@MustBe42' />

Parameters are also supported:

regula.custom({
   name: "MustBeSpecifiedNumber",
   params: ["number"],
   defaultMessage: "The answer must be equal to {number}",
   validator: function(params) {
      return this.value === params.number;
   }
});

And then:

<input type="text" name="something" data-constraints='@MustBeSpecifiedNumber(number=10)' />

You asked about validation groups, and that can be done in Regula as well:

<input type="text" name="street" data-constraints='@Required(groups=[AddressGroup])' />
<input type="text" name="city" data-constraints='@Required(groups=[AddressGroup])' />
<input type="text" name="state" data-constraints='@Required(groups=[AddressGroup])' />
<input type="text" name="zip" data-constraints='@Required(groups=[AddressGroup])' />

Then you can validate with:

var constraintViolations = regula.validate({
    groups: [regula.Group.AddressGroup] //AddressGroup property is automatically added
});

As far as HTML5 support and Asynchronous Validation, those features will be available in version 1.3 of Regula, which is currently in Alpha. I have a few minor features and documentation to update, but you should be able to checkout what is in on GitHub currently and it should work for you. HTML5 and Asynchronous Validation is mostly done.

With regard to HTML5 constraints, you can use the native attributes, or use Regula-wrapped versions which provide you more options like assignment to groups and custom messages. For example:

<input type="text" name="something" required="true" /> 

Will be recognized by Regula and validated. But you can also do this:

<input type="text" name="something" data-constraints='@HTML5Required(groups=[MyGroup], message="{label} is required!", label="something")' /> 
<input type="text" name="somethingElse" data-constraints='@HTML5Required(groups=[MyGroup], message="{label} is required!", label="somethingElse")' /> 

You can't normally do that with just the native HTML5 validation. An important thing to note however, is that the browser must support HTML5 validation for this to be able to work. Regula doesn't attempt to emulate HTML5 functionality since it involves more than just simple validation; it involves specific UI components as well. So for cross-browser compatibility you will need to use a polyfill or shim of some sort.

Asynchronous validation is also possible:

regula.custom({
    name: "AsyncConstraint",
    async: true,
    defaultMessage: "{label} did not validate properly.",
    validator: function(params, validator, callback) {
        jQuery.ajax({
            url: "myurl",
            dataType: "json",
            data: someData,
            success: function(data) {                    
                callback(data.successful)
            }
        });
    }
});

Then you can annotate your element with:

<input type="text" name="something" data-constraints='@AsynchronousConstraint' /> 

and validate with:

//Simply calling validate will validate all constraints on all elements
regula.validate(function(constraintViolations) {
    //do stuff with constraintViolations
});

It is also easy to do conditional validation and use pre-existing validators:

regula.custom({
   name: "ConditionalRequired",
   defaultMessage: "The answer must be equal to {number}",
   validator: function(params, validator) {
      var result = true;
      if(some condition is true) {
          result = validator.required(this, params, validator);
      }

      return result;
   }
});

The validator object basically gives you access to the raw validator-functions for each of the constraints.

Regula has a bunch of other features as well, such as compound constraints (basically like in JSR-303).

Regula doesn't have any UI-related logic, like displaying error messages as such. It is only a validation engine and so it only does that. How you want to display the error messages is up to you.

Hopefully you find this useful! As I mentioned before, the current version is 1.3.0; it is in alpha and you can get it from here.

Community
  • 1
  • 1
Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
  • Wow. I saw your other link also. This is very cool and yes it does do most of what I want. Thank you. I will give this a look. It is kind of overwhelming because there are a lot of features but I guess what I want to do is kind of complex also! – Dirty Randy Jul 11 '13 at 17:40
1

Some points that you should consider:

1-not all browsers support html5.

2-you can't customize default error messages for required fields.

3-you could use the pattern attribute and validate with a regular expression. External Resource

My suggestion: Take a look at a MVVM library such Backbone or Knockout.

http://backbonejs.org/#Model-validate

Thiago Custodio
  • 17,332
  • 6
  • 45
  • 90
0

HTML5 data-* attributes are useful for this kind of problems. http://www.slideshare.net/lensco/html5-data-attributes

They don't work well with XHTML doctypes, but they do on more lax ones, like HTML 4.01.

jQuery 1.9 (and I think prior versions too) allow you to do things like this:

$(someInput).data()

which will return an object with all data-* properties (in camelCase) and their respective values.

LexLythius
  • 1,904
  • 1
  • 12
  • 20
  • Hmm... that is interesting, but is there a library that will take care of most of this for me? Like, I would like to describe a custom validation rule and then use that in data-. – Dirty Randy Jul 11 '13 at 17:34