JavaScript - - By Thomas Greco

Easy Form Validation in AngularJS with ngMessages

Last fall, the ngMessages module was rolled out with the release of Angular 1.3. This added enhanced support for displaying messages to the user — typically error messages from form validation. Before the release of ngMessages, developers were forced to rely on directives such as ng-class and ng-show to display these errors. This resulted in cluttered, repetitive code.

Now, however, ngMessages provides the ability to display custom error messages without having to violate the D.R.Y. principle of coding — Don’t Repeat Yourself. And, as Angular steadily progresses towards version 2.0, Angular’s development team continues to roll out new features for it. Therefore, I thought it would be beneficial to demonstrate just how easy ngMessages makes the process of validating forms in AngularJS.

Getting started

This will be our basic template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>ngMessages demo</title>
  </head>
  <body ng-app="app">

    <script src="path/to/angular.min.js"></script>
    <script src="path/to/angular-messages.min.js"></script>
    <script>
      var app = angular.module('app', ['ngMessages']);
    </script>
  </body>
</html>

As you can see, we are loading Angular, followed by the ngMessages module, before injecting it into our application. For those of you wishing to folow along at home, the code for this tutorial is available on GitHub. For the impatient, you can also skip to the demo at the end of the article.

Next we are going to create a form with the following fields:

  1. First Name
  2. Last Name
  3. Email Address
  4. Phone Number
  5. Message

I will add a required attribute to all of the fields (as they will be compulsory), as well as using an ng-model directive to bind them to properties on the current scope.

<form name="exampleForm" class="myForm" required>
  <label>First Name:</label>
  <input type="text" name="userFirstName" ng-model="firstName" required />

  <label>Last Name:</label>
  <input type="text" name="userLastName" ng-model="lastName" required />

  <label>Email Address:</label>
  <input type="email" name="userEmail" ng-model="email" required />

  <label>Phone Number:</label>
  <input type="email" name="userPhoneNumber" ng-model="phoneNumber" required />

  <label>User Message:</label>
  <textarea type="text" name="userMessage" ng-model="message" required></textarea>
</form>

Enter ngMessages

Now let’s dive into the code and check out how ngMessages allows us to use the attributes we specify on the inputs for simple form validation.

Required Fields

The first thing you should take note of is that the form is named exampleForm. When using the ng-messages directive, we pass it an angular expression evaluating to a key/value object (typically the $error object on an ngModel instance). In our case this will be the name of the form, chained to the name attribute of the respective form field, chained to the aforementioned $error object.

<div ng-messages="exampleForm.userFirstName.$error">

Once that is done, you just need to nest a div containing an ng-message attribute inside of the ngMessages div. The value passed to the ng-message attribute will depend upon the directives we added to the input field; in this case, the value will be required.

That will give us:

<label>First Name:</label>
<input type="text" name="userFirstName" ng-model="firstName" required />
<div ng-messages="exampleForm.userFirstName.$error">
  <div ng-message="required">This field is required</div>
</div>

<label>Last Name:</label>
<input type="text" name="userLastName" ng-model="lastName" required />
<div ng-messages="exampleForm.userLastName.$error">
  <div ng-message="required">This field is required</div>
</div>

Email

Next, we want to make sure the user enters a valid e-mail address. Luckily, HTML5 makes this a pretty easy task. In the previous example, the name attribute of the input fields took the value of text, however email addresses take the value of email. Just like the example above, you simply chain the form name, input name, and error validator, and pass it to the ng-messages attribute, in order to activate the error messages. We can then add an additional div containing the ng-message attribute that takes the value of email. By doing so, we can target the email value just like we target the required value.

<label>Email Address:</label>
<input type="email" name="userEmail" ng-model="email" required />
<div ng-messages="exampleForm.userEmail.$error">
  <div ng-message="required">This field is required</div>
  <div ng-message="email">Your email address is invalid</div>
</div>

Regular Expressions

As we continue along, we will be using ng-pattern directive to validate the user’s phone number. For those who are unfamiliar with ng-pattern, it is used to ensure an input field matches the regular expression that is passed into the attribute. In this case, we will be validating the user’s phone number by passing the following regex into the ng-pattern attribute:

/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/

This will match the following formats (and ensure we accept a valid ten-digit phone number):

(123) 456-7890
123-456-7890
123.456.7890
1234567890
+31636363634
075-63546725

The ng-pattern error message is activated by passing in the value of pattern into ng-message, which can be seen in the code below:

<label>Phone Number:</label>
<input type="email" name="userPhoneNumber" ng-model="phoneNumber" 
       ng-pattern="/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/"
       required/>
<div ng-messages="exampleForm.userPhoneNumber.$error">
  <div ng-message="required">This field is required</div>
  <div ng-message="pattern">Must be a valid 10 digit phone number</div>
</div>

Validating phone numbers with a regex is a bit of a tricky subject (and, to be honest, simpler is often better). To learn more about this, you can check out this SitePoint article, or this Stack Overflow thread. To learn more about regular expressions in general, you can read this article on the Mozilla Developer Network.

Minlength and Maxlength

The final thing we want to do is validate the user’s message. The name of this field is userMessage and it is required just like the examples above. This time however, we will utilize the ng-minlength and ng-maxlength attributes. Both of these attributes take integer values which will equal a set number of characters — the ng-minlength attribute is used to set the number of characters a user is limited to, whereas the ng-maxlength attribute sets the maximum numbers of characters that a user is allowed to enter.

In the example below, you will see that we are passing error messages into both the minlength and maxlength values. By doing this, the error message for the minlength value will appear until the user reaches the desired number of characters. Additionally, the error message defined for maxlength will appear once the user surpasses the set number of characters passed into the ng-maxlength attribute.

<label>User Message:</label>
<textarea type="text" name="userMessage" ng-model="message" 
          ng-minlength="100" ng-maxlength="1000" required>
</textarea>
<div ng-messages="exampleForm.userMessage.$error">
  <div ng-message="required">This field is required</div>
  <div ng-message="minlength">Message must be over 100 characters</div>
  <div ng-message="maxlength">Message must not exceed 1000 characters</div>
</div>

Now that we have validated all of the necessary fields, you should have a fully functional form that displays whatever message you desire based on the input tags for your form!

See the Pen Easy Form Validation in AngularJS with ngMessages by SitePoint (@SitePoint) on CodePen.

A Final Tweak

One of the best things about ngMessages, and Angular in general, is the ability it gives you to utilize different directives together. For instance, you can hide the error messages by adding the statement ng-if="exampleForm.inputName.$dirty after the ng-messages directive. To show you how this is done, I have added the ng-if statement to the userMessage section of the form that we have just created. Now, there no error messages until the field is touched, or dirty.

<label>User Message:</label>
<textarea type="text" name="userMessage" ng-model="message" 
          ng-minlength="100" ng-maxlength="1000" required>
</textarea>
<div ng-messages="exampleForm.userMessage.$error" 
     ng-if="exampleForm.userMessage.$dirty">
  <div ng-message="required">This field is required</div>
  <div ng-message="minlength">Message must be over 100 characters</div>
  <div ng-message="maxlength">Message must not exceed 1000 characters</div>
</div>

Conclusion

Hopefully by now you have a pretty firm grasp of the ngMessages API, and how it can be used to easily perform form validation. In addition to what we have seen here, there are a bunch of other tricks you can do. For example, Angular allows you to tie ngMessages and ngAnimate directives together and create custom animations that reveal and hide custom error messages. I encourage you to utilize this new feature in Angular, and get as comfortable with it as possible — the ngMessages module offers a variety of different functionality when dealing with form data that you surely do not want to give up!

If you have any questions, or would like to share your opinion on this technique, feel free to reach out to me in the comments.

Sponsors
Login or Create Account to Comment
Login Create Account