Web UI validation (December 2014 edition)

I’m working on a new website using jQuery + Bootstrap + AngularJS + WebAPI. One of the first things I needed was UI form validation. I thought:

“Ok! There is all this new, nifty technology – this must be a breeze, nowadays!”

Alas, I was incorrect. Woefully incorrect. The state of “validation” currently, is a train wreck. What is the problem?

  • No single mechanism does everything you need.
  • There are close to 1.7 bajillion different “plug-ins”, “frameworks”, and custom one-off solutions.
  • You have to pick a primary way to do validation: HTML5, AngularJS, JQuery, or some other plug-in – and then get it to work with everything you are using.

So, what will I do? I’ll give you yet another custom, one-off solution. HOWEVER, I think this is the simplest, reasonable alternative as of right now.

The problem:
I started with a “registration” form. I can type any values into the fields. Instead, I want to not let the user continue until the form is valid. That is, make sure that the e-mail address is valid, the password should meet minimum requirements, and the password confirmation should match the first password. Only then, should you be able to submit the form.

image

I figured: let’s start with HTML5 Validation. That’s the lowest-common-denominator. I can at least cover things like “required” and “regular expressions”. That enforces the form is valid before submitting. Meaning, the fields all have the (Bootstrap) blue glow and only give me validation errors when I try to submit the form:

image

and

image

I only see these when I try to submit the form – not on keypress, or if I navigate to another field.

 

One way to make this nicer (Bootstrap + AngularJS):
I spent quite a bit of time trying to get JUST the bootstrap or JUST the AngularJS validation stuff working and I couldn’t do it. I ultimately came up with this solution.

OK, so at this point, we have fields that do HTML5 validation when I submit the form, but it doesn’t show any real-time indication of whether the field is validated. The form fields are currently set up like this:

<div class="form-group">
    <label for="loginName" class="col-sm-2 control-label">E-mail Address:</label>
    <div class="col-sm-10">
        <input type="email" placeholder="jdoe@example.com" class="form-control"
                ng-model="model.LoginName" id="loginName" required="required" />
    </div>
</div>

<div class="form-group">
    <label for="password1" class="col-sm-2 control-label">Password:</label>
    <div class="col-sm-10">
        <input type="password" placeholder="••••••••••••••••" class="form-control"
                ng-model="model.Password" id="password1" pattern="^(?=.*d).{4,50}$" required />
    </div>
</div>

<div class="form-group">
    <label for="password2" class="col-sm-2 control-label">Password (again):</label>
    <div class="col-sm-10">
        <input type="password" placeholder="••••••••••••••••" class="form-control"
                ng-model="model.PasswordConfirm" id="password2" pattern="^(?=.*d).{4,50}$" required />
    </div>
</div>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

First – let’s tackle the AngularJS part. I use AngularJS and some JavaScript to determine if the current model field is valid.  One frustrating thing I found, which I ended up using to my advantage was the the model field is set to ‘undefined’ if it fails HTML5 validation! So, at any point if the data in that field no longer passes HTML5 validation, the ng-model will be set to ‘undefined’.

Put another way, we put responsibility of validation on HTML5, which reports back ‘undefined’ for any fields which fail HTML5 validation. We can use this to our advantage by having this support method in our AngularJS controller:

$scope.isValid = function(modelItem) {
    return (typeof modelItem === 'undefined');
};

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

So, I now have a way to determine if the current field is valid. So, now I can take advantage of the pretty features offered in Bootstrap 3. I now show/hide CSS classes or glyphs based on whether the current field has passed HTML5 validation using something like this:

<div class="form-group has-feedback"
        ng-class="(!isValid(model.LoginName)? 'has-success' : 'has-error')">
    <label for="loginName" class="col-sm-2 control-label">E-mail Address:</label>
    <div class="col-sm-10">
        <input type="email" placeholder="jdoe@example.com" class="form-control"
                ng-model="model.LoginName" id="loginName" required="required" />
        <span class="glyphicon glyphicon-ok form-control-feedback"
                aria-hidden="true" ng-show="!isValid(model.LoginName)"></span>
        <span class="glyphicon glyphicon-remove form-control-feedback"
                aria-hidden="true" ng-show="isValid(model.LoginName)"></span>
    </div>
</div>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see, “has-success” will be added if model.LoginName is valid, and “has-error” will be added if it’s not. Further down, the ok glyph is added if it’s valid, and remove glyph if not. That results in something more ideal:

image

Each field updates and changes color on a per-keypress level now. Then, if you try to submit the form, it will give you the popup message about how validation failed.

image

Summary:
Again, there are almost unlimited ways to do UI validation and none of them are very appealing. This was the least offensive way I ran across which gives a pretty decent result, so I thought I’d write it down!

Posted in Computers and Internet, Development Tools, General, JQuery, Mobile, New Technology, Security, Uncategorized
3 comments on “Web UI validation (December 2014 edition)
  1. Binoj Daniel says:

    This is pretty nice. Good post.

    Like

  2. […] Binoj Daniel on Web UI validation (December 2014 edition) […]

    Like

  3. Jamie Dixon says:

    This helped me out a lot. Thanks!

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 5 other followers

%d bloggers like this: