Using ngMessages directive in AngularJS

ngMessages has been introduced in AngularJS 1.3.0 beta-8. This actually can be one of the most used directives depending on the amount of error/success messages and loaders we show to the user in our application.

As the name suggests, ngMessages directive is used to show messages in your application. Messages can be of any type, wether an ajax call error message or a form validation error. But ngMessages can be used in many other scenarios as well, like showing a handsome loader to your user while an ajax call is in progress.

Previously, we had to use ng-if or ng-switch or even ng-hide/show to show some kind of messages to the user. There have been many approaches to this but ngMessages makes it more efficient and enables resusability thus keeping your code DRY.

How it works

To understand how ngMessages directive works, lets see the markup below:

    <div ng-messages='ajaxRequest'>
        <div ng-message='serverError'>Server Error! Please Try again.</div>
        <div ng-message='notFound'>Oops! Resource Not Found!.</div>
        <div ng-message='error'>Request  Failed! Try Again.</div>
        <div ng-message='success'>Request Success</div>
    </div>

What ng-messages directive does is, it keeps a check on the key/value pair of the object passed and once a key evaluates to true then that ng-message block is shown. In above example, ajaxRequest object must look something like below:

    ajaxRequest = {serverError: false, notFound: false, error: true, success: false};

In the above case, error is true which results in the error message being shown to the user. This example showed how we can have our custom objects in scope and make ng-messages to work on its values. Lets look at a more automated scenario, i.e., forms where we don't need to have a custom object.

    <form name='demoForm'>
      <div>
        <label for='username'>Email:</label>
        <input type="text" name="username" id="username" placeholder="Enter your username" ng-model='form.username' ng-minlength='5' ng-maxlength='10' required/>
        <div ng-messages='demoForm.email.$error'>
            <div ng-message="required">This field is required!</div>
            <div ng-message="minlength">Username too short!</div>
            <div ng-message="maxlength">Too long to be a Username!</div>
        </div>
      </div>
      <div>
    </form>

In the above form, we have used the $error object which is exposed by ngModel directive. $error object consists of the key/value pairs for all the validation conditions, thus showing the ng-message block whose key evaluates to true. The ng-message block is shown in the order they appear, for eg. if required is true and minlength is true then required block will be shown as it is placed first in the HTML markup.

Message Templates and Overriding Messages

ngMessages directive also enables us to reuse messages in our application. What one can do is make an external file which has all the messages and include it wherever required in the application.

Lets consider an example:

    //messages.html - contains all the messages
    <div ng-message='serverError'>Request Failed Due to Server Error!</div>
    <div ng-message='notFound'>Not Found!</div>
    <div ng-message='inProgress'> Please Wait! </div>
    <div ng-message='required'> This field is required! </div>
    <div ng-message='minlength'> This field is too short!</div>
    <div ng-message='maxlength'> This field is too long!</div>
    <div ng-message='email'> Email is not valid!</div>

Now lets include this template in our form:

    <form name='demoForm'>
      <div>
        <label for='email'>Email:</label>
        <input type="email" name="email" id="email" placeholder="Enter your email" ng-model='form.email' required/>
        <div class='formMessage' ng-messages='demoForm.email.$error' ng-messages-include='messages.html'></div>
      </div>
    </form>

By using the ng-messages-include, the ng-messages directive starts using the messages.html template to show the messages thus keeping the code DRY. Also the directive enables us to override any of the messages in the template, for eg. if we want to show some other message for the required criteria, we can do it as below:

    <form name='demoForm'>
      <div>
        <label for='email'>Email:</label>
        <input type="email" name="email" id="email" placeholder="Enter your email" ng-model='form.email' required/>
        <div class='formMessage' ng-messages='demoForm.email.$error' ng-messages-include='messages.html'>
            <div ng-message='required'> Username cannot be blank !</div>  //Overriding the default message from the template with ours
        </div>
      </div>
    </form>

Conclusion

ngMessages directive has been kept out of the core and can be found in a seperate file angular-messages.js. Like other modules, this also needs to be included and injected into your angular application as below:

    var app = angular.module('myApp', ['ngMessages']);

You can find the working examples of ngMessages at this plunker written by me. Do let me know if you have any feedback/suggestions or doubts.

comments powered by Disqus