The Joy of Angular Form States

I love Angular. When Angular first started coming into the public eye, I was ecstatic. I fell in the love with the Model View Whatever architecture, and the ease of keeping otherwise messy JavaScript and jQuery from doing behind the scenes DOM manipulation. Instead Angular allowed on-the-fly data bindings from your client side JavaScript to your front end HTML. The ease! The simplicity! The frustration! Anyone familiar with Angular may be familiar with the following graph, showing the learning curve many developers experience with the framework.

At this point in my career, I am firmly in the "Most Awesome Framework Ever" category (with only occasional lapses into "DOOMED!!!!" mode). Now, finally to the point of this particular piece -- Angular form states. Using this framework, HTML form management becomes, in my opinion, much simpler. You can bind all of your inputs to a model and validate the form using Angular's form states.

As of version 1.2.28, the four available form states are ng-valid which indicates the validity of the form and inputs based on the constraints put upon them (ng-maxlength, for example). ng-invalid is the inverse of it. The ng-pristine means the input or field has not been interacted with, while ng-dirty indicates the user has attempted to enter something into the field. Unfortunately, ng-pristine does not record on-blur events, which means if a user tabs through the inputs, they are not recorded as dirty. The lack of on-blur recognition caused no end of issues during validation, if the user never actually interacts with the form.

Once version 1.3.0 was released, new states were added that made validation much easier by recognizing on-blur events: ng-touched. All inputs and forms start out as ng-untouched until the user causes an on-blur event, whether by clicking on an input or tabbing through it. Below is an example form using ng-touched to show validation messages:

<form name="form" novalidate>  
    <label for="uEmail">E-mail:</label>
    <input type="email" ng-model="email" name="email" required />
    <div ng-show="form.uEmail.$touched && form.uEmail.$invalid">
      <span ng-show="form.email.$error.required">Email is required.</span>
      <span ng-show="form.email.$error.email">Email address is not 
          valid</span>
    </div>
</form>

The novalidate tag on the form eliminates the normal HTML5 browser validation, in order to avoid two versions of validation showing at once. The example also demonstrates some of the different errors you can check on form inputs.

And lets not forget the beer that inspired this fine Friday entry. Sometimes you just need a good standby, like Blue Moon on Draught with an orange slice. Usually it is more of a summer drink for me, but it was perfect for the moderately warm sunny day we had down South. And on that note, its Friday, and I have Terrapin Liquid Bliss in a growler in my fridge. But that's a beer for another time!