This tutorial is out of date and no longer maintained.
Today we’ll be looking at the ways that Angular helps us do form validations.
Note: We have updated this article for Angular 1.3 and the new ng-touched feature.
We’ll focus on client-side validation and using the built-in Angular form properties. Here’s a quick demo.
See the Pen AngularJS Form Validation by Chris Sevilleja (@sevilayha) on CodePen
Now that we know what we want, let’s get to building.
Angular provides properties on forms that help us validate them. They give us various information about a form or its inputs and are applied to a form and inputs.
Property | Class | Description |
---|---|---|
$valid | ng-valid | Boolean Tells whether an item is currently valid based on the rules you placed. |
$invalid | ng-invalid | Boolean Tells whether an item is currently invalid based on the rules you placed. |
$pristine | ng-pristine | Boolean True if the form/input has not been used yet. |
$dirty | ng-dirty | Boolean True if the form/input has been used. |
$touched | ng-touched | Boolean True if the input has been blurred. |
Angular also provides classes on the form and its inputs so that you can style each state accordingly.
<form name>.<angular property>
<form name>.<input name>.<angular property>
We will use a simple form to demonstrate.
We will need 2 files:
index.html
Our code to display the formapp.js
Our Angular application and controller (barely any code at all)index.html
<!DOCTYPE html>
<html>
<head>
<!-- CSS ===================== -->
<!-- load bootstrap -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<style>
body { padding-top:30px; }
</style>
<!-- JS ===================== -->
<!-- load angular -->
<script src="http://code.angularjs.org/1.2.6/angular.js"></script>
<script src="app.js"></script>
</head>
<!-- apply angular app and controller to our body -->
<body ng-app="validationApp" ng-controller="mainController">
<div class="container">
<div class="col-sm-8 col-sm-offset-2">
<!-- PAGE HEADER -->
<div class="page-header"><h1>AngularJS Form Validation</h1></div>
<!-- FORM -->
<!-- pass in the variable if our form is valid or invalid -->
<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate> <!-- novalidate prevents HTML5 validation since we will be validating ourselves -->
<!-- NAME -->
<div class="form-group">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="name" required>
</div>
<!-- USERNAME -->
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
</div>
<!-- EMAIL -->
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="email">
</div>
<!-- SUBMIT BUTTON -->
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div><!-- col-sm-8 -->
</div><!-- /container -->
</body>
</html>
A few key points to note here:
ng-model
to our inputs so that we have data from our forms bound to Angular variablesng-minlength
and ng-maxlength
on username will create those rulesname
input is requiredemail
input is type=“email”Angular provides many validation rules that we can use in addition to ng-minlength
and ng-maxlength
.
These are the available parameters for an Angular input to create validation rules. Read the Angular input directive for more information.
<input
ng-model="{ string }"
name="{ string }"
required
ng-required="{ boolean }"
ng-minlength="{ number }"
ng-maxlength="{ number }"
ng-pattern="{ string }"
ng-change="{ string }">
</input>
Now that we have our simple form, let’s create our Angular app and controller that we have already applied to it using ng-app
and ng-controller
.
app.js
// create angular app
var validationApp = angular.module('validationApp', []);
// create angular controller
validationApp.controller('mainController', function($scope) {
// function to submit the form after all validation has occurred
$scope.submitForm = function(isValid) {
// check to make sure the form is completely valid
if (isValid) {
alert('our form is amazing');
}
};
});
We will use novalidate
on our form. This is a good practice since we will handle the validation ourselves. If we let our form do it, it will look pretty ugly.
Now the real fun begins. We get to start using Angular properties. First, let’s disable our submit button. We only want it disabled if our form is $invalid
.
...
<!-- SUBMIT BUTTON -->
<button type="submit" class="btn btn-primary" ng-disabled="userForm.$invalid">Submit</button>
...
With just that little code (ng-disabled
), our form button will be disabled if the form is $invalid
. This means that our name
input field is required and our email
input field requires a valid email.
ng-show
ng-valid and ng-invalid will automatically determine if an input is good based on the rules placed on it in your form.
Let’s go through and add an error message for each of our inputs if they are not $valid
and have already been used (since we don’t want to show an error before they’ve been used).
...
<!-- NAME -->
<div class="form-group">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">You name is required.</p>
</div>
<!-- USERNAME -->
<div class="form-group">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.username.$error.minlength" class="help-block">Username is too short.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">Username is too long.</p>
</div>
<!-- EMAIL -->
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="email">
<p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">Enter a valid email.</p>
</div>
...
Just like that, Angular will automatically determine if we should show an error based on an input’s $invalid
and $pristine
properties.
Better Validation Messages: There is now a new way to show error messages. AngularJS Form Validation with ngMessages
Angular already provides classes on our inputs and our forms based on if they are valid or not. Look at the table at the beginning of this article for those classes (ng-valid
, ng-invalid
, ng-pristine
and ng-dirty
).
You can style those in CSS if you like. You can do anything you like with those classes. There will even be classes based on the certain rules applied if you wanted to get really specific.
.ng-valid { }
.ng-invalid { }
.ng-pristine { }
.ng-dirty { }
.ng-touched { }
/* really specific css rules applied by angular */
.ng-invalid-required { }
.ng-invalid-minlength { }
.ng-valid-max-length { }
Since we are using Bootstrap, we will use the classes they provide (has-error
). This will get us that nice error and color around our form-group
.
ng-class
allows us to add classes based on an expression. In this case, we want to add a has-error
class to our form-group if an input is $invalid
and not pristine
.
The way it works is ng-class="{ <class-you-want> : <expression to be evaluated > }"
. For more information, read the Angular ngClass docs.
...
<!-- NAME -->
<div class="form-group" ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="user.name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">You name is required.</p>
</div>
<!-- USERNAME -->
<div class="form-group" ng-class="{ 'has-error' : userForm.username.$invalid && !userForm.username.$pristine }">
<label>Username</label>
<input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.username.$error.minlength" class="help-block">Username is too short.</p>
<p ng-show="userForm.username.$error.maxlength" class="help-block">Username is too long.</p>
</div>
<!-- EMAIL -->
<div class="form-group" ng-class="{ 'has-error' : userForm.email.$invalid && !userForm.email.$pristine }">
<label>Email</label>
<input type="email" name="email" class="form-control" ng-model="user.email">
<p ng-show="userForm.email.$invalid && !userForm.email.$pristine" class="help-block">Enter a valid email.</p>
</div>
...
Now our form has the correct Bootstrap error classes.
Sometimes it is not desirable to show errors while a user is typing. The errors currently show immediately as a user is typing into the form. This happens because of Angular’s great data-binding feature. Since everything changes immediately, it can be a downside when talking about form validation.
For the scenario where you only want to show errors after a form is submitted, you would adjust the above code a little bit.
ng-disabled
on the submit button since we want a user to be able to submit a form even if it is not fully valid.submitForm()
function, just add $scope.submitted = true;
. This stores the submitted variable as true as soon as the form is submitted.ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }"
to ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine && submitted }"
. This ensures that the error will only show after the form is submitted. You would need to adjust all the other ng-class
and ng-show
to account for this variable.Now the form only shows errors if the submitted
variable is set to true
.
Only showing errors after clicking out of an input (also known as blur) is a little more complicated than validating on submit. Validating a form on blur requires a custom directive. A directive will allow you to manipulate the DOM.
We have updated this article to add the new ng-touched
feature in Angular 1.3. This helps us handle blurred inputs!
Now once we fill out all our information correctly, our form submit button will be active. Once we submit our form, we’ll see the alert message we set up.
With just a few simple lines we now have:
As you can see, it is easy to use the built-in Angular form validation techniques to create a client-side validated form.
As it stands, it is not a simple process to do validation after a user clicks out of an input. The Angular team is aware of this and they have said they plan to add more states to handle things like form.submitted
, input.$visited
, input.$blurred
, or input.$touched
. Here are some resources for the future of form validation:
Hopefully sooner rather than later it’ll be easier to do validation and account for different states of our application.
Note: Updates.
Edit #1: Added information about validating after form submit or on blur. Also added resources. Edit #2: Changed the process form function to take the valid parameter. Helps to create testable controllers. Thanks to Fredrik Bostrom for the tip.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!