Javascript Validation

Take a form that collects user comments for use in a Javascript application. Once submitted, the form’s fields would flow into some kind of comment model via a function that might look something like this:

function getComment (form) {
    var comment = {
        body: form.body,
        email: form.email
    }
    return comment;
}

No problems there—as long the only purpose is to copy form values over. If the comment’s fields are going to be used anywhere else in the application, though, we’re going to need a little more secret sauce. At a minimum, we would at least want to ensure that the title, body, and email address tied to the comment have all been filled out. And if we’re going that far, we might as well make sure that the title is filtered for profanity, the e-mail address is valid, and so on.

Javascript won’t do this itself, but we can construct custom data types that will. Take the e-mail field, for instance. We can define a new Email type that will automatically check an e-mail (passed as a parameter—address) against a basic regular expression. If the address is valid, we’ll get an instance of the Email type back. If it isn’t, we won’t get anything:

function Email(address) {
    if(address.test(/([^@]+)@(\w+)(\.\w+)*\.(\w{2,6})/)){
        this.address = address;
        this.toString = function () { return this.address };
        return this;
    }
    return {};
}

(note: there are lots of ways to test e-mail addresses. But getting even close to right is really, really, hard. We’ll settle for “enough”, here, and trust a server to actually check it somewhere down the line)

Now, we can update the getComment function to make sure that any e-mail addresses that get passed by our users are valid. If they aren’t, the comment won’t be created:

function getComment (form) {
    var comment = {
        body: form.body,
        email: form.email
    }
    if (comment.email.address) {
        return comment;
    }
    return null;
}

Invalid e-mails will cause getComment to return null, making it an easy business to keep the comment from going any further.

var newComment = getComment(form);
if (!newComment) {
    alert('hey! that wasn\'t valid!');
}

We’re almost finished! The final step in all of this is to wrap this approach up into a generic function that can be recycled for other data types. Rather than testing for a particular attribute, let’s now take the next logical step and make sure that the object—whether an Email or something else entirely&mash;has the class that it’s supposed to. In its simplest form, we would use:

function fillObject (obj, params) {
    var x;
    for (x in obj) {
        if (params[x] === NULL || params[x].constructor !== obj[x]) {
            return false;
        } else {
            obj[x] = params[x];
        }
    }
    return true;
}

Now, any field in comment that doesn’t match its prescribed type will cause the function to return in disgrace. Validation doesn’t get much easier than that!

var comment = {
    body: String,
    email: Email
}

if (fillObject (comment, {
    title: form.title,
    body: form.body,
    email: new Email(form.email)
})) {
    alert('Comment submitted.');
} else {
    alert('Invalid submission. Please try again!');
}

In closing

Every MVC library worth its salt provides a framework—or at least some kind of hook—that will help ease the validation process. Use them. This approach is simply one tool among many that can help ensure user data is what it’s supposed to be.

Let’s keep in touch

Reach out on Twitter or subscribe for (very) occasional updates.

Hey, I'm RJ: digital entomologist and intermittent micropoet, writing from the beautiful Rose City.