How AngularJS Helps Validate Forms

With AngularJS, you can apply a wide variety of checks and effects to form elements. This blog will go over some of the basics. Not only does Angular allow you to validate user input using built-in and custom directives, but it also automatically furnishes your elements with helpful CSS classes.

Angular will help you take advantage of the many basic validation options included in HTML5, such as the required attribute and additional input types like email and URL. Angular extends the available options with their own directives like ng-maxlength and ng-minlength

Setup is Easy

Checking the state of any form element is easy as long as you remember to name your form and its inputs.

<div ng-app="MyApp" ng-controller="ctrlForm">
  <form name="myForm" novalidate>
    <label for="txtEmail">Your email</label><br>
    <input type="email" name="email" id="txtEmail" ng-model="email" required />
    <label for="interests">What interests you?</label><br>
    <textarea name="interests" id="interests" ng-model="interests" 
        ng-maxlength="255" ng-minlength="10" required></textarea>
    
    <input type="submit" value="Submit" />
  </form>
</div>

Placing the optional novalidate attribute on your form and will disable native form validation.

Any named form elements will now be available in this format:

formName.inputName.propertyName    // In markup

The ng-form directive can be used in place of a form element. This is useful if you want to nest forms, which is normally prohibited.

<div ng-form="myForm"> ... </div>

Validation Tests

Want to know if the input element has been touched or modified by the user? Check $dirty, $touched, or $pristine:

myForm.email.$dirty    // Returns true if the user has modified this element

In our markup we added the HTML required attribute to our email input and specified that it should be a valid email address using type. We can test if this input is valid according to those restrictions by checking $valid or $invalid

myForm.email.$valid    // Returns true if this element has passed all tests

This is certainly useful, but perhaps you want more in-depth information about which validation tests failed for a particular element. The $error property contains the full collection of tests and a boolean value for each to indicate validity. If a test fails, this value will be true.

formName.inputName.$error.testName

ex. myForm.interests.$error.maxLength

These properties can be easily leveraged to dynamically reveal error messages or other clever things. Our friend ng-show is especially handy here:

<input type="email" name="email" id="txtEmail" ng-model="email" placeholder="Email Address" required />

<div class="error-wrapper" ng-show="myForm.email.$dirty && myForm.email.$invalid">
  <span ng-show="myForm.email.$error.required">Email is required</span>
  <span ng-show="myForm.email.$error.email">Please enter a valid email address</span>
</div> 

Several of these directives can also be applied to the form itself, and not just individual elements. Using the ng-disabled directive, you can deactivate the submit button until the user has edited the form:

<input type="submit" value="Submit" ng-disabled="myForm.$pristine">

Better yet, keep their paws off that submit button until the form passes validation:

<input type="submit" value="Submit" ng-disabled="myForm.$invalid">

Custom Directives{{cta(‘209aad85-272d-4e83-8cdc-4f30262bc921′,’justifyright’)}}

Learn how to add a custom validation test to an element from my guide about writing your own directives. Define your own checks easily, and gain the ability to compare against other scope values using Angular’s parse service.

Directives are also useful for form presentation. They can be used to add classes, behaviors, and properties by attaching event listeners. Since validation works in real-time as the user types, it would be pretty bothersome to have error messages appear while you are editing. To solve that, we can write a custom directive to ensure the messages stay hidden until the input loses focus:

angular.directive('customFocus', [function() { 
  var FOCUS_CLASS = "custom-focused"; //Optional: Toggle a class and style that!     
  return {       
    restrict: 'A', //Angular will only match the directive against attribute names       
    require: 'ngModel',        
    link: function(scope, element, attrs, ctrl) {         
      ctrl.$focused = false;
          
      element.bind('focus', function(evt) {   
        element.addClass(FOCUS_CLASS);           
        scope.$apply(function() {ctrl.$focused = true;});
               
      }).bind('blur', function(evt) {
        element.removeClass(FOCUS_CLASS);           
        scope.$apply(function() {ctrl.$focused = false;});         
      });       
    }     
  }
}]);

Attach this directive to your elements by giving them a new attribute called custom-focus:

<textarea name="interests" id="interests" ng-model="interests" ng-maxlength="255" ng-minlength="10" required custom-focus></textarea>

NOTE: Directives should be given camel case names (“customFocus”), but angular will be looking for a dash-delimited name (“custom-focus”) when searching the markup for a match. It is best practice to prefix the names of your custom directives to ensure they won’t conflict with directives or tags released in future versions of angular or HTML. In particular, avoid names beginning with “ng.”

The last step is to test $focus before showing any errors that may be inappropriate or untimely. For example, don’t show the minimum length error for this text area until focus changes, but do show the maximum length error immediately so users know when to stop:

<div class="error-wrapper" ng-show="myForm.interests.$dirty && myForm.interests.$invalid">
  <span ng-show="myForm.interests.$error.maxlength">
    Must be less than 255 characters
  </span>
  <span ng-show="myForm.interests.$error.minlength && !myForm.interests.$focused">
    Must be more than 10 characters
  </span>
</div>

Styles

Angular also provides us with a set of CSS classes named similarly to the directives. Combine them in interesting ways to create more refined forms.

ng-pristine, ng-dirty, ng-touched, ng-valid, ng-invalid

Want all those distractions to go away when the user is editing an element? Our custom directive supplies us with the perfect class just for that:

input.ng-valid:not(.custom-focused) {
  border-color: green;
}

input.ng-invalid.ng-dirty:not(.custom-focused) {
  background-color: red;
}

Want to create stand-out forms that respond to your users? Combine your own talents with the power of AngularJS and you will find it’s easier than ever!

Check out this plunk to view a demo of these concepts:


Found this blog post useful? Learn more about Easy Dynamics Corp and the {{cta(‘33985992-7ced-4ebd-b7c8-4fcb88ae3da4′,’justifyright’)}}technologies we use:

{{cta(‘5e73a80d-1cb0-47a2-a64c-1dc252ec2301′,’justifyleft’)}}

Author

Leave a Comment