PROGRAMS

Form Validation in AngularJS with ngMessages

In the previous article, we have seen Angular Form Validation using HTML5 attributes, Form State Properties and Angular directives such as ng-minlength, ng-maxlength. As we could see this approach is simpler and easy but not efficient/flexible in case of multiple messages for a single field.

With the HTML5/form properties/directives approach, each error message is showed explicitly only if that error occurs. It means, for each error message to be displayed, the condition needs to be applied. This becomes tedious in case of multiple errors. This is where Angular Ng-Messages is introduced.

The ngMessages module provides enhanced support for displaying error messages within templates (when rendering message objects with key/value object). Instead of using Javascript code or ng-If/ng-Show statements within your forms to show/hide the error messages specific to the state of the input field, the ngMessages and ngMessage directives are designed to handle the complexity and priority sequencing of the messages.

ngMessages:

What is a ngMessage?

ngMessage is a directive (a component of the ngMessages module) with the purpose to show and hide a particular message.

For ngMessage to operate, a parent ngMessages directive on a parent DOM element must be situated since it determines which messages are visible based on the state of the provided key-value pairs that ngMessages listens on.

Note: ngMessageExp is similar to ngMessage, but instead of the static value, it accepts an expression to be evaluated for the message key.

The ngMessages directive is a collection of the key-value pair where each key needs to be associated with the child element (ngMessage) which will then show or hide the error message based on the truthiness of the key’s value in the collection. Basically, ngMessages is used to display the error messages for an input field using its $error object exposed by the ngModel directive.

The child element of the ngMessages directive is matched with the keys in the ngMessages keys collection by ngMessage or ngMessageExp directive. On matching, if the value of key in the collection is true, that particular error message is shown.

How to use ngMessages?

ngMessages is a module which can hold multiple child elements, which can be expressed as a collection of ngMessage. ngMessages directive can be used as an “Attribute” or as an “Element”. Let us look at the syntax of both as follows.

As an Attribute:

<ANY ng-messages="expression" role="alert">
  <ANY ng-message="stringValue">Error Message</ANY>
  <ANY ng-message="stringValue1, stringValue2, ...">Error Message</ANY>
  <ANY ng-message-exp="expressionValue">Error Message</ANY>
</ANY>

As an Element:

<ng-messages for=”expression” role=”alert”>
<ng-message when=”stringValue”>Error Message</ng-message>
<ng-message when=”stringValue1, stringValue2, …”>Error Message</ng-message>
<ng-message when-exp=”expressionValue”>Error Message</ng-message>
</ng-messages>

Let us take a look at the below example to understand how to use ngMessages directive. We have the input of type text called Name. This input is must be entered by the user but length should be between 3 and 8 characters. So here validations to be applied are:  required, minlength and maxlength.

<form name="loginForm">
      <!--USERNAME -->
     <div class="form-group">
 <label>Name*</label>
 <input type="text" name="name" class="form-control" ng-model="name" ng-minlength="3" ng-maxlength="8" required>
 <div ng-messages="loginForm.name.$error" role="alert">
  <div ng-message="required">Please enter a value for this field.</div>
  <div ng-message="minlength">name is too short.</div>
  <div ng-message="maxlength">name is too long.</div>
 </div>
     </div>
</form>

As you can see in the above code, we have ngMessages evaluated to $error object of ‘name’ and 3 ngMessage directives evaluated for each one of the validation keys.

Recommended Read:

Prioritizing the sequence/order of Messages:

By default, ngMessages will display only one message at a time for a particular key-value collection. If more than one message key in a collection is true at the same time, then which message to be shown is determined by the order of messages in HTML template code. It means the first placed message is prioritized as first.

As you can see in above example, if all three message keys are true then required will be displayed first. As you enter a character required message will disappear and the minlength message will be displayed. And similarly, after minlength disappears, the maxlength message will be displayed.

Display multiple messages at the same time:

Since ngMessages allows only one message element at a time, ng-messages-multiple or multiple attributes can be applied to ngMessages container element to cause it to display applicable multiple message elements at the same time.

<div ng-messages="loginForm.name.$error" ng-messages-multiple>  //to do  </div>
OR
<ng-messages  for="loginForm.name.$error" multiple>  //to do  </ng-messages>

Reuse of Messages:

In addition to prioritization, ngMessages supports Message Reusability. Here messages can be reused by defining the messages in a separate file or in an inline template and referring it to the ngMessages. This allows the generic collection of messages to be reused across any part of the application.

This reusability is achieved using ng-messages-include directive.

<script type="text/ng-template" id="error-messages">
  <div ng-message="required">This field is required</div>
  <div ng-message="minlength">This field is too short</div>
</script>
<div ng-messages="loginForm.name.$error" role="alert">
  <div ng-messages-include="error-messages"></div>
</div>

Sometimes this generic message collection may not be useful enough to match all input fields. So ngMessages provides the ability to override the message defined in the remote template by redefining the messages in container directive.

<!-- a generic template of error messages known as "my-custom-messages" -->
<script type="text/ng-template" id="my-custom-messages">
  <div ng-message="required">This field is required</div>
  <div ng-message="minlength">This field is too short</div></script>
<form name="loginForm">
  <label> Name
 <input type="text" name="name" ng-model="name" minlength="3" maxlength="8" required />
  </label>
  <!-- any ng-message elements that appear BEFORE the ng-messages-include will
       override the messages present in the ng-messages-include template -->
  <div ng-messages="loginForm.name.$error" role="alert">
    <!-- this required message has overridden the template message -->
    <div ng-message="required">You did not enter your email address</div>
    <!-- this is a brand new message and will appear last in the prioritization -->
    <div ng-message="maxlength">Your name is too long</div>
    <!-- and here are the generic error messages -->
    <div ng-messages-include="my-custom-messages"></div>
  </div>
</form>

 

A simple example using ngMessages:

We will take a simple login form and we will validate the form using ngMessages.

As explained in the last article, Form Validation in AngularJSwe will use same login page with three fields: Name, Username (should be an email of the user) and Password. We shall perform the same validations using ngMessages. So validation requirements are like,

  1. Name field is required
  2. Name field length must be between 3 and 8.
  3. Username is required and should be a valid email.
  4. The password should be in length between 6 and 8 characters.

For this application, we will require 3 files: index.html and angular app app.js. We need reusable message template i.e. messages.html

Let us create an index.html page with all the above-explained fields.

//index.html
<!DOCTYPE html>
<html>
<head>
    <!-- CSS -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />
    <!-- JS -->
    <script src="https://code.angularjs.org/1.4.0/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-messages.js"></script>
    <script src="app.js"></script>
</head>
<body ng-app="validationApp" ng-controller="mainController as m">
<div class="container" style="width:600px">
    
    <!-- PAGE HEADER -->
    <div class="page-header">
      <h3>AngularJS Form Validation using ngMessages</h3>
    </div>
       <!-- pass in the variable if our form is valid or invalid -->
    <form name="loginForm" novalidate>
        <!-- NAME -->
        <div class="form-group" ng-class="{ 'has-error' : 
             loginForm.myName.$touched && loginForm.myName.$invalid }">
            <label>Name*</label>
            <input type="text" name="myName" class="form-control"
            ng-model="m.name" ng-minlength="3" ng-maxlength="8" required>
            
            <div class="help-block" ng-messages="loginForm.myName.$error" 
                 ng-if="loginForm.myName.$touched">
              <p ng-message="required">Your name is required.</p>
              <p ng-message="minlength">Your name is too short.</p>
              <p ng-message="maxlength">Your name is too long.</p>
            </div>
        </div>
        
        <!-- USERNAME -->
        <div class="form-group" ng-class="{ 'has-error' : 
                  loginForm.userName.$touched && loginForm.userName.$invalid }">
            <label>UserName(email)*</label>
            <input type="email" name="userName" class="form-control" 
                   ng-model="m.userName" required>
                   
            <div class="help-block" ng-messages="loginForm.userName.$error" 
                 ng-if="loginForm.userName.$touched">
              <p ng-message="email">Please enter a valid email.</p>
            </div>
        </div>
        
        <div class="form-group" ng-class="{ 'has-error' : 
             loginForm.password.$touched && loginForm.password.$invalid }">
            <label>Password*</label>
            <input type="password" name="password" class="form-control" 
                   ng-model="m.password" ng-minlength="6" ng-maxlength="8" 
                   required>
                   
            <div class="help-block" ng-messages="loginForm.password.$error" 
                 ng-if="loginForm.password.$touched">
              <div ng-messages-include="messages.html"></div>
            </div>
           
        </div>
        
        <button type="submit" class="btn btn-primary" 
              ng-disabled="loginForm.$invalid">
          Submit
        </button>
    </form>
    </div>
</body>
</html>

 

As you can see in the above code, we are using ngMessages directive for handling validations. ngMessage directive will display the message according to the true value of its particular key present in the key collection of ngMessages. Also, we are using a remote template for defining message keys and referring the same in the index page. This is done to show the reusability of messages. The submit button is disabled if the form is invalid. When all the validations get successful, the button gets enabled.

Now let us create an angular app and controller page i.e. app.js

// create angular app - app.js
var validationApp = angular.module('validationApp', ['ngMessages']);

// create angular controller
validationApp.controller('mainController', function($scope) {

});

Next, we will have message keys template file i.e. messages.html

<p ng-message="required">This field is required</p>
<p ng-message="minlength">This field is too short</p>
<p ng-message="maxlength">This field is too long</p>
<p ng-message="email">This needs to be a valid email</p>
<p ng-message="password">This needs to be a valid password</p>

This file is just the collections of messages defined using ngMessage directive. To use messages defined in this file, ng-messages-include attribute allows us to refer this file. You can see it on the index page for the password field. When the key in the input definition matches with the key in the template file and based on the truthiness of it, the message is shown.

 

Let us take a look at the output of this application.

1) Initially when the app is loaded.

 

2) Validations for the Name fieldWhen Name field is simply touched but not entered and if the user moves to next field, the below error is shown.

3) Text length validation. When the user starts entering the Name field, based on the length of the value, it displays minimum length message or maximum length message as shown below.

As defined, the name should be between 3 to 8 character length. Since entered value is of 2 characters below error is displayed. If it exceeds the max length, “Your name is too long” message will be shown.

4) Highlighting a field. When the user doesn’t enter any value in the UserName field and goes off the focus of the field, it shows highlighted border (meaning required). As we do not have the error message defined the or required key, just the border is highlighted.

5) Email validation. As the user starts entering a value in the Username field, if it does not meet a valid email type, it displays the below-shown error. A valid email should have an ‘@’ character followed by other characters.

6) When the user fills in all the fields and if they pass all the validations, the Submit button gets enabled.

Conclusion:

NgMessages provides a simple module for error handling in AngularJS as compared to ng-If or ng-show. This eases a developer’s life by reducing the efforts as it supports the reusability and prioritization.

Preeti Dhavali

Leave a Comment
Share
Published by
Preeti Dhavali

Recent Posts

5 Ways Technology is Changing the World of Marketing

The marketing industry is continually evolving with new strategies and technologies catalyzing growth. To understand…

1 day ago

How Cyber Security is Changing in the World of Digital Technology

Cyber security is becoming increasingly critical as we move into the digital age. As the…

1 week ago

Everything You Need To Know About Create React App

The configuration of resources can be a time-consuming and difficult operation while creating a React…

1 month ago

Causes of CyberCrime and Preventive Measures

          Rapid technological growth and developments have provided vast areas of…

2 months ago

How Data Lineage will Improve Business Practices

How often have you thought about changing the way that you store and use data?…

2 months ago

10 Dominating Programming Language for Mobile App In 2022

Programming Languages are a set of rules that aid in transforming a concept into a…

2 months ago