JavaScript
Article
By Thomas Greco

Easy Form Validation in AngularJS with ngMessages

By Thomas Greco

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.

  • James Hibbard

    Hi Lukas, thanks for pointing that out. I’ve added a link to your article along with the link to the Stack Overflow thread.

  • Thomas Joseph Greco

    Hey @lukaswhite:disqus thank you for your input. I was simply trying to illustrate how ng-pattern can be used in correlation with ng-messages to validate regex patterns for the sake of the tutorial.

    For anyone else who may have found this a bit troubling, I would recommend that you do a bit of research and find whatever regex pattern may best suit your location. Additionally, this response had me do a bit of research, and I found that ng-pattern allows you to define multiple regex patterns inside of controllers. You can check this out more through this link – http://stackoverflow.com/a/17459276/4372822

    • This is how it is possible to make sixty-five dollars /an hour… After being without work for six months , I started freelancing over this web-site and now I could not be happier . 3 months~ have passed since being on my new job and my income is around 5000 dollarsmonth -Check Link on MY~DISQUS~PROFILE for more information

  • Andy Troyer

    I have a question in regard to ngMessages…. I have 2 fields I need to validate. Each though need to fire when the value of the other changes (they are dependant on each other). As an example…. if you have an amount “textbox” and a dropdown of amounts. Your validation basically need to fire if both the amount dropdown AND the amount textbox are not filled in. If one of them has a numeric value then you are good. If either fails then you need to show a validation message and prevent submission. Ive yet to see any good examples of ngMessage validations which fire based on the value of a different control. For instance I need the textbox error to fire “when” I change the dropdown to a blank “select one” as well as I need the dropdown validation to fire when I clear the textbox from the amount previously entered. Any help would be appreciated.

    It seems like firing another controls validation when its supporting control doesn’t work for me. Even if I could fire both ngMessage validations when at least one is not selected (or entered) would be fine.

  • Andy Troyer

    I’ll give that a try.. thanks

  • Andy Troyer

    I have another scenerio that I’m not sure how to handle. Lets say you have a “range” which dynamically changes when you choose a different product from a list of radio buttons. Say you choose product “A” which has a range of 50 – 100. You enter “55” in the amount textbox which validates as correct. You then choose a different product (product “B”) which has a different range of 100 – 150. What happens is the amount textbox is not evaluated again and never fires as wrong. Here is an example of the amount textbox which uses a “range directive” to fire off the error:

    Any help on this is appreciated. Didn’t know if you should try and force some sort of dirty flag on the amount textbox so that when the other control (radio button list of products) changes it will force things to be re-evaluted. Appreciate it.

  • Kevin

    thank you it helps me so much….

  • Hi, Great Post!..and thanks for sharing …… Is it possible to have a regex checked with ng-pattern for a “name” input so that a number isn’t placed there? say [a-zAZ] and is invalid if done so…? Cheers

  • Suraj Kharve

    Thanks for sharing that plunker link @matsko:disqus

  • Samad

    Hi,
    How could we achieve this if my for contains components?

  • Claudenir Freitas

    Nice man!

  • Ankit

    Can we have some validations for drop downs ? Drop down should be required. I have a month and year drop down, i need to validate that the month and year selected should not be earlier than the current date.

  • I’d like validate count with checkbox and custom directive but I can’t it.

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.