ThatValidator

Powerful and extensible form validation that doesn't suck

Download Version 1.0.0 — development
View on Github

Fast and lightweight

ThatValidator comes in at 1.44kb gzipped and minified and has zero dependancies. ThatValidator respects your DOM with as little queries as possible and won't slow down your pages.

Highly Customizable

ThatValidator doesn't include a bunch of default styling you then have to override. It allows you to do whatever you need to do for any kind of form.

Clean HTML

Most importantly, ThatValidator respects your DOM by not forcing you to clutter it with myriad data- attributes. It aims to keep your HTML clean and semantic while giving you powerful configuration through javascript.

Why

Did you make yet another form validation library?

Form validation isn't hard to hack together, but for complicated forms it can quickly become a mess. There's a definite benefit to keeping your event listeners organized and managing all the focus, blur, keypress/keyup events.

Moreover, html should remain clean and semantic and your form validation library shouldn't require jQuery or other dependencies. We also needed a form validator for our own website :).

HTML shouldn't look like this:

                        
<form>
    <label for='languages'>Languages</label>
    <input type="text" class="form-control" name="languages" data-oregano-conditionalrequired='["[name=\"question1\"]:checked", "yes"]' data-oregano-validate-if-empty data-oregano-success-class="" data-oregano-conditionalrequired-message="This value is required since you are a programmer!" />

    <label for='why'>Why?</label>
    <input type="text" class="form-control" name="why" data-oregano-conditionalrequired='["[name=\"question2\"]:checked", "no"]' data-oregano-validate-if-empty data-oregano-success-class="" data-oregano-conditionalrequired-message="This value is required since you do not eat dog food!" />
</form>
<!-- What the heck, that's only 2 inputs! -->
                        
                        

It should look like this:

                        
<form>

    <label for='languages'>Languages</label>
    <input name='languages' type="text"/>

    <label for='why'>Why?</label>
    <input name="why" type="text"/>

</form>
<!-- Ah, much better -->
                        
                        

Ok, so how do I validate then

Here's an example ThatValidator configuration, highly annotated

                
/*---------------------------

       Example Usage

  --------------------------*/

var myValidator = new ThatValidator('#myForm', {

    /* Called when the form is filled and there are no errors */
    completed: function()
    {
        alert('Form filled and it is valid');
    },

    /* Configure your validators through the fields object. */
    fields: {

        '#email': {

            /* Create your validation tests for the #email field here */
            /* `validations` functions return an array of errors */
            /* An empty array or returning `true` means no errors */
            validations: function(field) {

                var errors = [];

                /* ThatValidator doesn't come with any validation tests */
                /* Write your own tests, or use a validation library such as */
                /* https://github.com/chriso/validator.js */
                if(!ChrisoValidator.isEmail(field.value))
                    errors.push('Please enter a valid email.');

                return errors;
            } 
        },

         /* A function as a value is an alias for `key: {validations: function() { }}` */
        '#password': function(field) {
                var errors = [];

                /* Have as many validations/tests as you would like! */
                if(field.value.length < 6)
                    errors.push("Password must be at least 6 characters.");

                if(!/[^a-zA-Z]/.test(field.value))
                    errors.push("Password must contain a symbol or number.");

                if(errors.length == 2)
                    errors = ["Password must be at least 6 characters and contain a symbol or number."];

                return errors;
            }

        },

        '#username': {

            /* handler functions are run in the scope of this object, so you can cache */
            /* other objects for reuse here! */
            loadingIndicator: document.getElementById('username-loading-indicator'),

            /* An ASYNC example*/
            validations: function(field, callback) {

                show(this.loadingIndicator);

                checkNameIsAvailable(field.value).then(function(result) {

                    var errors = [];

                    if(!result.ok)
                        errors.push('Name is taken');

                    callback(errors);

                    hide(this.loadingIndicator);
                });

                /* async validation functions MUST return undefined */
            }

        },

        /* the key can be any valid document.querySelectorAll() selector! */
        /* In this example, this will apply to ALL inputs inside the form */
        /* Allowing you to handle errors in a common way */
        /* Use any selector (e.g., `.required`) if you don't want every field required */
        'input': {

            validations: function(field)
            {
                var errors = [];

                if(field.value.length == 0)
                    errors.push('Field is required.');

                return errors;
            },

            /* Called when the field is defocused or the user  */
            /* stops typing and the field does not pass validations*/
            onError: function(field, errors)
            {
                addClass(field, 'error'); /* do whatever floats your boat,  $(field).addClass('error') */
                removeClass(field, 'valid');

                /* You provide this function, do what you want with the errors */
                showErrorLabel(field, errors);
            },

            /* Same as onError except the field validated succesfully */
            onValid: function(field)
            {
                removeClass(field, 'error');
                addClass(field, 'valid');

                removeErrorLabel(field);
            },

            /*  There are also optional onFocus, onBlur, onKeyPress and onKeyUp handlers. */
            onKeyPress: function(field, event)
            {
                console.log('You typed inside of ', field);
            }

        },

    }

  })



                
            
expand collapse

A Demo Is Worth 1,000 lines of code

Here are a few examples that show the flexibility of ThatValidator

30 Day Trial Form

Disclaimer: This is our trial form. Not trying to advertise it here, we just think it's a really awesome form.

Generic Signup Form

Just your day-to-day signup form with nifty-difty validations using ThatValidator.

Coming Soon

More examples are on the way, but in the meantime here's a kitten.

Ok, I'm sold

Now how do I use this thing?

  1. Get it from NPM
    npm install thatvalidator --save

    or grab it here
  2. Require it
    var ThatValidator = require('ThatValidator');
  3. Create a validator for each form and start setting it up.
    var myValidator = new ThatValidator(form, config)

    tip: you can reuse common validations across validators!
  4. Use
    myValidator.isValid()
    to check if your form has been filled and has no errors & use
    myValidator.validate(callback)
    to run through the validations again.
  5. That's it. The rest is up to you. Check out the examples for some sweet use cases, or help out by submitting issues, features requests, and pull requests.