Almost every website uses forms to perform different tasks like signing up users or obtaining their contact information. It is very important to make sure that a user who is filling out the form is at least entering valid information in the input fields.
It is also necessary to show a detailed error message to the users so they can fill in the form correctly. This process can become very complicated when you have to deal with a lot of form elements, each of which will need its own custom error messages. To ease the pain, Angular 1.3 added a new module called ngMessages to help developers validate forms with ease.
The ngMessages module gives you the ability to display custom error messages to your users without writing repetitive code. In this tutorial, you will learn how to use this module to validate your forms. You will also learn how to load the error messages externally and only show the messages when they are actually needed.
A Basic Example
Let's start by validating a single input field with and without the help of ngMessages to see the usefulness of this module. Without using ngMessages, the markup for the input element will look similar to the following code:
<form name="formValidation"> <label>Username</label> <input type="text" name="username" ng-model="inputname" ng-minlength="6" ng-maxlength="12" required> <p ng-show="formValidation.username.$error.minlength">Username should have at least 6 characters.</p> <p ng-show="formValidation.username.$error.maxlength">Username should have at most 12 characters.</p> <p ng-show="formValidation.username.$error.required">Providing a username is mandatory.</p> </form>
You will also need the following JavaScript code:
angular.module('app', []);
All other form elements will need to be validated similarly. This will make the markup very repetitive, increasing the chances of errors. If you decided to use ngMessages to validate the same form input, the markup would have looked similar to the following code:
<form name="formValidation"> <label>Username</label> <input type="text" name="username" ng-model="inputname" ng-minlength="6" ng-maxlength="12" required> <div ng-messages="formValidation.username.$error"> <p ng-message="minlength">Username should have at least 6 characters.</p> <p ng-message="maxlength">Username should have at most 12 characters.</p> <p ng-message="required">Providing a username is mandatory.</p> </div> </form>
The JavaScript code will now become:
angular.module('app', ['ngMessages']);
Here, we have used the ng-messages
directive to group the error messages together. The value passed to the ng-messages
directive follows the pattern formName.inputName.$error
. In our case, this evaluates to formValidation.username.$error
.
Similarly, you could also get the value of the ng-messages
directive for all the other fields. ngMessages relies on the $error
object exposed by the ngModel directive to determine if error messages should be shown or hidden on the webpage. It loops through the $error
object looking for a key that matches the values of any of the ng-message
directives.
Here is a working example that shows the above validation code in action:
Validating a Form
In this section, we will be validating a form with a username, password and an email field. The markup for the form will look similar to the following code:
<form name="formValidation"> <label>Username</label> <input type="text" name="username" ng-model="inputName" ng-minlength="6" ng-maxlength="12" ng-pattern="/^\w+$/" required> <div ng-messages="formValidation.username.$error"> <p ng-message="minlength">Username should have at least 6 characters.</p> <p ng-message="maxlength">Username should have at most 12 characters.</p> <p ng-message="required">Providing a username is mandatory.</p> <p ng-message="pattern">Username can only be alphanumeric with an optional underscore.</p> </div> <label>Password</label> <input type="text" name="userPassword" ng-model="inputPassword" ng-minlength="6" ng-maxlength="12" required> <div ng-messages="formValidation.userPassword.$error"> <p ng-message="minlength">Password should have at least 6 characters.</p> <p ng-message="maxlength">Password should have at most 12 characters.</p> <p ng-message="required">Providing a password is mandatory.</p> </div> <label>Email</label> <input type="email" name="userEmail" ng-model="inputEmail" required> <div ng-messages="formValidation.userEmail.$error"> <p ng-message="email">Please enter a valid email address.</p> <p ng-message="required">Providing an email is mandatory.</p> </div> </form>
As you can see, the markup required for validating different form elements is very similar. One important change in this case is the addition of the ng-pattern
directive. The pattern we are using here ensures that the entered username only has alphanumeric characters and an underscore. The \w
in /^\w+$/
stands for word characters like A-Z, a-z, 0-9 and _.
You should try typing a different username in the username field. After some time, you will notice that the form does not complain about a character not being alphanumeric if it was typed before the first six characters or after the first 12 characters. This behavior is not very user friendly.
For example, let's say some of your users start their username with an exclamation mark. They will have to wait until they have typed six more characters to get the error about only using alphanumeric characters. It will be very frustrating for them to start typing the username again from the beginning.
By default, ngMessages only shows one error to the user at a time. That's why the message about invalid characters could not be shown before a user had typed more than six characters. Moreover, ngMessages uses the order in which you entered the error messages as a hint to determine their priority.
If you have provided the minimum character message before the alphanumeric error, ngMessages will wait until the minimum character error has been resolved before it shows the alphanumeric error.
Here is the same form with the error messages presented in a different order.
You can also show all the applicable error messages to a user at once using the ng-messages-multiple
. However, seeing multiple error messages as soon as users start typing in an input field can overwhelm them.
Reusing Error Messages
There is still a lot of repetition in our markup. If you want to show the same error message for different input fields, it doesn't make sense to repeat it for each of them. The ngMessages module can help you write generic error messages only once and include them in your form whenever the need arises. Here is the markup to create a form that displays generic error messages to the users.
<script type="text/ng-template" id="generic-messages"> <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> </script> <form name="formValidation"> <label>Username</label> <input type="text" name="username" ng-model="inputName" ng-minlength="6" ng-maxlength="12" ng-pattern="/^\w+$/" required> <div ng-messages="formValidation.username.$error"> <p ng-message="pattern">Username can only be alphanumeric with an optional underscore.</p> <p ng-message="maxlength">Username cannot be longer than 12 characters.</p> <div ng-messages-include="generic-messages"></div> </div> <label>Password</label> <input type="text" name="userPassword" ng-model="inputPassword" ng-minlength="6" ng-maxlength="12" required> <div ng-messages="formValidation.userPassword.$error"> <div ng-messages-include="generic-messages"></div> </div> <label>Email</label> <input type="email" name="userEmail" ng-model="inputEmail" required> <div ng-messages="formValidation.userEmail.$error"> <p ng-message="required">This field is required.</p> <p ng-message="email">Please enter a valid email address.</p> </div> </form>
Just like the previous case, the priority of a message is determined by its place in the template. You can also override the generic messages provided in the template by including a custom error message inside individual fields. The error messages can also be loaded from a separate file using the following code:
<div ng-messages="formValidation.userPassword.$error"> <div ng-messages-include="path/to/generic-messages.html"></div> </div>
Showing Errors Only When Required
You can make your form more user friendly by only showing error messages when a user has actually made an error while filling out the forms. For example, you can opt to only show the required field error when a user actually skips over an input element.
This can be achieved by using either the ng-show
or ng-if
directive along with $touched
and $dirty
. In the case of $touched
, the error message is shown as soon as the input loses focus. In the case of $dirty
, the error message shows up as soon as the input becomes invalid.
<div ng-messages="form.username.$error" ng-if="form.username.$touched"> <div ng-messages="form.username.$error" ng-if="form.username.$dirty"> <div ng-messages="form.username.$error" ng-show="form.username.$touched"> <div ng-messages="form.username.$error" ng-show="form.username.$dirty">
Here is the demo that shows the difference between $touched
and $dirty
.
Conclusion
In this tutorial, you learned how easy it is to validate the input of different kinds of form elements using ngMessages. You also learned how to reuse the same error messages multiple times to avoid repetition and how to prioritize different error messages.
You can also use both ngMessages and ngAnimate together to use custom animations to show or hide your error message. A tutorial about using the ngAnimate module will also be published on Envato Tuts+ soon.
If there are any tips that you would like to share with fellow readers or if there is any question that you would like to ask, let me know in the comments.
No comments:
Post a Comment