AngularJS Form Validation

Today we’ll be looking at at the ways that Angular helps us do form validations. We’ll be talking more on forms using Angular (just like our other article: Submitting AJAX Forms: The AngularJS Way). Don’t worry though, that article is not required.

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


  • Name is required
  • Username is not required, minimum length 3, maximum length 8
  • Email is not required, but has to be a valid email
  • Form submit is disabled if the form isn’t valid
  • Show a required or invalid email error
  • Alert awesome if submitted correctly

Now that we know what we want, let’s get to building.

Angular Form Properties $valid, $invalid, $pristine, $dirty

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.

Angular also provides classes on the form and its inputs so that you can style each state accordingly.

Accessing Angular Form Properties

  • To access the form: <form name>.<angular property>
  • To access an input: <form name>.<input name>.<angular property>

Setting Up Our Form

We will use a simple form to demonstrate.


We will need 2 files:

  • index.html Our code to display the form
  • app.js Our Angular application and controller (barely any code at all)

Our Form Code index.html

<!-- index.html -->
<!DOCTYPE html>
    <!-- CSS ===================== -->
    <!-- load bootstrap -->
    <link rel="stylesheet" href=""> 
    	body 	{ padding-top:30px; }
    <!-- JS ===================== -->
    <!-- load angular -->
    <script src=""></script> 
    <script src="app.js"></script>

<!-- 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">
            <input type="text" name="name" class="form-control" ng-model="name" required>

        <!-- USERNAME -->
        <div class="form-group">
            <input type="text" name="username" class="form-control" ng-model="user.username" ng-minlength="3" ng-maxlength="8">
        <!-- EMAIL -->
        <div class="form-group">
            <input type="email" name="email" class="form-control" ng-model="email">
        <!-- SUBMIT BUTTON -->
        <button type="submit" class="btn btn-primary">Submit</button>

</div><!-- col-sm-8 -->
</div><!-- /container -->

A few key points to note here:

  • novalidate: This will prevent the default HTML5 validations since we’ll be doing that ourselves (ours will be much prettier)
  • We have applied ng-model to our inputs so that we have data from our forms bound to Angular variables
  • ng-minlength and ng-maxlength on username will create those rules
  • The name input is required
  • The email input is type=”email”

Validation Rules

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.

       ng-model="{ string }"
       name="{ string }"
       ng-required="{ boolean }"
       ng-minlength="{ number }"
       ng-maxlength="{ number }"
       ng-pattern="{ string }"
       ng-change="{ string }">

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.

Our Angular App Code app.js

// 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');



Disabling HTML5 Validation novalidate

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.


Disabling the Submit Button ng-disabled

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.

<!-- index.html -->

    <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.

Showing an Error Message 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).

<!-- index.html -->

	<!-- NAME -->
    <div class="form-group">
        <input type="text" name="name" class="form-control" ng-model="name" required>
        <p ng-show="$invalid && !$pristine" class="help-block">You name is required.</p>

    <!-- USERNAME -->
    <div class="form-group">
        <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>
    <!-- EMAIL -->
    <div class="form-group">
        <input type="email" name="email" class="form-control" ng-model="email">
        <p ng-show="$invalid && !$pristine" class="help-block">Enter a valid email.</p>


Just like that, Angular will automatically determine if we should show an error based on an inputs $invalid and $pristine properties.


Styling Classes

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 		{  }

	/* really specific css rules applied by angular */
	.ng-invalid-required 		{  }
	.ng-invalid-minlength 		{  }
	.ng-valid-max-length 		{  }

Adding Conditional Classes ng-class

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.

<!-- index.html -->

	<!-- NAME -->
    <div class="form-group" ng-class="{ 'has-error' :$invalid && !$pristine }">
        <input type="text" name="name" class="form-control" ng-model="" required>
        <p ng-show="$invalid && !$pristine" class="help-block">You name is required.</p>
    <!-- USERNAME -->
    <div class="form-group" ng-class="{ 'has-error' : userForm.username.$invalid && !userForm.username.$pristine }">
        <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>
    <!-- EMAIL -->
    <div class="form-group" ng-class="{ 'has-error' :$invalid && !$pristine }">
        <input type="email" name="email" class="form-control" ng-model="">
        <p ng-show="$invalid && !$pristine" class="help-block">Enter a valid email.</p>


Now our form has the correct Bootstrap error classes.


Only Showing Errors After Submitting the Form

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.

  1. You would need to take away the 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.
  2. You would add a variable after the form has been submitted. Inside of your submitForm() function, just add $scope.submitted = true;. This stores the submitted variable as true as soon as the form is submitted.
  3. Adjust the error rules from ng-class="{ 'has-error' :$invalid && !$pristine }" to ng-class="{ 'has-error' :$invalid && !$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

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 are writing up an article devoted specifically to that topic. In the meantime, here are some resources to create custom directives to handle blur:

All Done

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:

  • Input Validation
  • Form Errors
  • Custom Classes
  • Automatically disabled and enabled form
  • Custom Rules

As you can see, it is easy to use the built in Angular form validation techniques to create a client-side validated form.

The Future

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.

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.
This article is part of the AngularJS Forms series.

Chris Sevilleja

Design, development, and anything in between that I find interesting.

View My Articles

Stay Connected With Us
hover these for magic

Get valuable tips, articles, and resources straight to your inbox. Every Tuesday.

  • Joe Van Dyk

    If I start typing in an email address, I see an error immediately. Not a great experience.

    • Chris Sevilleja

      Completely agree with you. I’ve added extra information to this article about handling that scenario and am working on an article to handle a custom directive to only show validation after a user has clicked out of an input.

      Thanks for the feedback.

      • yunuskocyigit

        i think this is a good experience. because when i tried to click submit button and i see that moment “this is not a valid adress” i am getting angry. and i am asking to application “why didn’t you say from the start ?”

  • Matt Jordan

    I agree with Joe Van Dyk. That sort of immediate “error” reporting – before I’ve even finished typing anything – is annoying at best and potentially confusing at worst. All in all a terrible user experience.

    • Chris Sevilleja

      I agree with you and Joe. Angular doesn’t currently provide an easy way to see if a user has used and clicked out of a form. They have said they are adding that in the future but currently it will require a custom directive.

      I thought a custom directive was out of scope for a starter validation article like this but I appreciate the feedback. I’ve added info to this article about handling the blur or after a form is submitted and am also working on a directive article to only show validation after a user has clicked out.

      • Matt Jordan

        Thanks for the feedback. And apologies for only mentioning my complaint in my initial post: this is actually a very good tutorial overall and I appreciate you writing it. :)

  • Amul Patel

    great article.. trying to wrap my head around angular directives now.. Silly question.

    How are you embedding the sublime code in your blog entry (looks perfect…)

    • Chris Sevilleja

      Thanks. Angular directives are a little weird but once you get them, they are awesome. We’ll be doing a writeup on those soon.

      We are using for our code styling.

  • Pingback: Sceendy » My Workflow

  • Jason Lunsford

    I just posted a “thank you” message on another tutorial you wrote, 10 minutes ago tops. If the helpfulness of that former tutorial (to my current issue) was 7 out of 10, this one is 10 out of 10 – thanks again!

    Incidentally, I asked you a bunch of questions just answered here – predictive question answering, when do the rest of us Angular developers get this feature? :-)

  • Pingback: Submitting AJAX Forms: The AngularJS Way ♥ Scotch

  • Levon Tamrazov

    Hey Chris, thanks a lot for writing this. I am currently working on implementing this for a form, but I am getting an error on submission “TypeError: Cannot read property $valid of undefined”. This happens when I try to do the validation check before proceeding with submission (if $scope.formname.$valid). Its definitely in scope of the ctrl since all other form fields and ng-models get initialized just fine. I know its not much to go on, but any clue to what might be the issue? Thanks in advance!

    • Chris Sevilleja

      Can you throw the code up on a so I can take a look?

      • Levon Tamrazov

        Thanks for the quick response. Here is the plunk:

        The form opens in a modal on click on (“Edit”). Once you click “Save” in the form, that error comes up.

        Thanks again!

        • Levon Tamrazov

          Nevermind, just discovered the problem. Had to use (this.form-name) instead of $scope.form-name when doing the validation check… new to Angular so still haven’t grasped the difference between “this” and “$scope”.

          Thanks again for the great post.

          • Chris Sevilleja

            Gotcha. Glad it all worked out.

  • Brad Williams

    Great post! Is there a good way to make my own custom validator besides copy-pasting the code for one of the built-in directives such as ngMinLength and going from there? (ngPattern cannot cover all cases.) And related to this, how does server-side validation fit into this, i.e., user types a username that is already in use? Basically, can custom and server-side validation be integrated with the built-in stuff like form.$invalid?

  • Pingback: Collective #101 » CSS 3 & HTML 5 Links und Infos

  • Pingback: Collective #101 | CSS Snippets | FREE Online Magazine

  • Luka Peharda

    Great post! Thank you.

  • Pingback: Collective #101 | The Creative Web Project

  • Pingback: Form helpers @

  • Pingback: Collective #101 - Big Design Blog - Big Design Blog

  • Pingback: Collective #101 | Daniele Milana

  • Anders Hallundbæk

    What about IE8 support? Is there a great way of handling it when still using AngularJS Form validation?

    • Chris Sevilleja

      Angular uses HTML5 for its validation rules. IE8 doesn’t have support for HTML5 things like type=”email” and other things. I think you’d probably have to have some sort of fallback built in JavaScript to handle client-side validation. You can also always keep the server-side validation.

  • Chris Sevilleja

    I haven’t but I will. Pretty sweet site. Thanks for the link.

  • Pingback: AngularJS | Pearltrees

  • Royce Lithgo

    Only showing errors after submit… Finally! I’m pretty sure this is the first example I’ve seen of that. Thank you very much!

    Just wondering how difficult it would be to enhance your solution to hide an error message after the user modifies the invalid input. It’s also a little off putting for a user to see an error message when they’ve already corrected it (but haven’t pressed submit because they’re still correcting other errors).

    • Chris Sevilleja

      Interesting. I hadn’t thought of that use case. I guess you could reset the submitted variable as soon as someone left the input? I’m sure some combination of custom variables and $dirty, $valid, $invalid, or $pristine could combine to make the solution.

      You could create a custom directive that would reset the submitted variable or do the validation. I’ve seen some custom directives that could do validation only after clicking out of an input also.

      • Royce Lithgo

        Wouldn’t resetting the submitted variable make all other input errors hide? You only want to hide the error on the field that the user just corrected, but remaining errors should still be visible.

        I’m thinking an additional variable is required to track the condition when an invalid field has been modified and awaiting validation from submit. But i don’t think that its very elegant.

        • Chris Sevilleja

          No it’s not very elegant. The Angular team has said they’ll be adding new states to validation so hopefully that will help problems like this.

  • Pingback: Angular Form Validation | My Dev Note

  • sebdavid


    In the case of validating field after form submit, I think the control on $pristine attribute of form elements is useless, because of the new “submitted” variable, isn’t it ?

    So the control could be :
    ng-class=”{ ‘has-error’ :$invalid && submitted }”

    I was facing a problem during my dev, I thought about an issue with angular, but finally the origin of the problem was the $pristine check. Have a look to my posts here ::

    • Chris Sevilleja

      You’re right. You could remove the $pristine check since submitted is there. Good find.

  • Pingback: Handling Checkboxes and Radio Buttons in Angular Forms ♥ Scotch

  • Fredrik Boström

    Thanks for a great tutorial. I noticed, however, that you break the de-coupling of the controller and view with your validation check in the submitForm() function:

    if ($scope.userForm.$valid)

    This breaks for example unit testing the controller, since it depends on the view having created the userForm variable into the scope.

    A better approach could perhaps be to pass the form validity state into the submitForm function like this:

    and in the controller

    function submitForm(isValid) {
    if (isValid) { alert(“Saved”); }

    This way the controller doesn’t need to know anything about the view and we’re not coupling it to the view, which also makes unit testing easier.

    • Chris Sevilleja

      Great point. I’ve updated the tutorial and plnkr and attributed you in the edits section. Thanks for the awesome feedback!

  • Pingback: Collective #101 |

  • Logan Danger Black

    Very good article. I used this as a base tutorial for creating my first very first Angular form, and I’m very pleased with the results vs. the time I spent on it. I agree with the comments (Matt and Joe) that immediate validation is a drag, but also agree that custom directives are beyond the scope of the article. That being said, I’d definitely be interested in seeing a follow up on how to delay validation til on blur or perhaps a better (more complex) solution, until after the user has had a .25 – .5 second delay in typing, that way they may still be focused on the input that needs fixed, rather than having to click back up the form.
    On the whole though – good article.

    • Chris Sevilleja

      I actually was going to make a directive to handle blur but then it got a little more complicated and I was hoping that ngBlur would get released in a coming update by Angular.

      I will try again today and see if it can be done pretty easily. I wonder if we can use this:

      • Logan Danger Black

        Heres a solution I just implemented. It allows you to show/hide validation on blur using “form.fieldname.$focused” (see “Show validations only after blur”, half way down the page.)

  • Shrestha

    Chris, thanks for the detailed post. ng-newsletter has an example of custom directive to validate only after blur –

    • Chris Sevilleja

      ng-newsletter is always such a great resource. thanks for the link.

  • Pingback: AngularJS Form Validation |

  • Pingback: How to find what all fields changed in AngularJS Form | DiscVentionsTech

  • Dan

    why use !$pristine instead of $dirty

    • Chris Sevilleja

      No reason. You can use either. That’s just the one I chose.

  • Ravi Mone

    chris, I appreciate your work, but i have a doubt, from couple of weeks, Just to validate 3 fields of a form, we have to add so many code, and the validation part for one input tag, occupies many tags, then how about a form have more than 10 fields, and if i have many forms in other pages, each time i have to do this. Why not we have a plugin like jquery validation-engine, so that we can just add class names for validations.

    • Chris Sevilleja

      It does seem like a lot of extra code. The main way to look at Angular applications however is that Angular handles the data. It validates the data and binds it to our objects. Having this binding is what simplifies our processing the form even though it does seem like a lot more code.

      Using jQuery to validate means that it can complicate the process of passing variables to and from our Angular controllers and our views. For larger projects, handling the data in Angular and having it bound to $scope variables will help in the long run since we have a single source of truth for our data.

  • Fin

    hi Chris. thanks for the good article. But I have a situation here, lil bit strange i think.

    I use the following statement to validate my password input field. but it’s now working. The errors doesn’t show up.

    ng-show="userRegistration.password.$error.minlength && submitted"

    what could be wrong with my code?

    • Chris Sevilleja

      Make sure you set the length rule with the password input.


  • echomrg

    Hi all, i’ve been looking for new, better way to do “basic” things like validation and i stumbled on this post but i have to admit, to the risk of looking like a troglodyte who can’t grasp how a wheel works, i’m having troubles understanding the basic idea on which everything here is based.

    I’ve been working in web development for a while and lately everything was about the separation between content/data, presentation and logic.

    yet here we have a brand new framework, something on the cutting edge, putting a lot of the validation logic straight inline into the html code. i can understand defining fields length and stuff like that, they can be considered integral to the data itself. but i think i’d have nightmares about maintaining code where the logic hiding and showing error messages is interspersed among the html code.

    since I really don’t believe i’m such a genius that i’m seeing something nobody else sees (the contrary is quite more probable) i was wondering if there’s someone willing to help me see the elephant i’m clearly missing :)

    thanks in advance,

    • Chris Sevilleja

      Hey Marcello, I’ve been asked this a few times. While it does move a lot of information into the views, one way to think of it is that the logic is being handled by Angular in the form model. It just makes things easier for quick and easy validation.

      I understand the very valid argument that you would want to not have the logic in the views. There are ways to do validation so that you can be happy with the separation of views and logic. You can create your own validation service that is a completely separate Angular module and then use that in your controller.

      It is a bit more work and it would be cool to see a better way to do this.

      • echomrg

        thanks for the answer and for the pointer :)
        right now i’m going through a few basic tutorials just to be sure to understand everything from the start, when i’m done i’ll try validation too.

        (sure setting up node.js on linux, through a proxy is a PAIN)

  • trudesign

    I’m having trouble with the initial example. I have the same code set-up the same way, however the $invalid function is never set to false once my fields are all filled in, so my ‘save’ button is never actionable. Any ideas? I wish I could show a plunkr but I can never get plunker working with angular (never said I was smart, lol)

    • trudesign

      Aha, I think I found my issue, I was basing ng-required off of a scope variable I set elsewhere. ng-required=”{{required}}”. Didn’t need the moustache brackets within the NG expression. Works well now.

  • trudesign

    Do you know if it’s possible to affect the form’s validity state based on an associated model setting? For instance, I have model.value, which is what my input is affecting, and Lets say that is set up by a directive that brings up a modal box, etc. I want to set the form to invalid, if model.value exists, BUT does not exist. As in, you can’t have one without the other. I can’t seem to get them to play well together though, because I’m not using required on any inputs. I thought that I could just affect the model.$invalid property in my JS and that would roll up into the form.$invalid call. Any thoughts?

    • Chris Sevilleja

      Hey sorry for the late response. Can you check if is $pristine at the start of the form or is that not possible since it is set by a directive?

      I think that you could add some checks into your function that processes the form. You could pass in the data for with the function like $scope.processForm(formValid, fireValid).

  • avidgoffer

    Chris, great article! How would one do delayed validation? I have a situation that allows the user to edit and leave the data in any state up until a point they want to “submit” the data. At this point how can I highlight the elements red?

    • Chris Sevilleja

      Hello sorry for the late response. On submission you could set a variable called submitted to true. Then do the check in the form for the variable. So you would check if the field is valid and if the form is submitted.

  • Boštjan Pišler

    Great tutorial, thanks.
    One thing, in the “Only Showing Errors After Submitting the Form” the ng-class should be “$invalid && submitted” because a user can submit the form even if it’s still pristine.

  • Johannes

    Hi, nice article.

    but I got the “submitted” Version only running when I am writing: ng-show=”frm.inputVorname.$error.required && (!frm.inputVorname.$pristine || submitted)”

    because when I am klicking Submit button without entering any thing into the Inputfields, then no error is shown. With the above Solution everything works fine.

  • Pingback: AngularJS Multi-Step Form Using UI Router | Bee Scripts

  • Marcel Stör

    This is a great tutorial, thanks!

    We got tired of adding/maintaining the cumbersome and tedious AngularJS constraints on each an every constrained input field. That’s why we built valdr. It allows to define all constraints in a JSON document. That’s concise and reusable.

    Java projects using Bean Validation can take this one step further with valdr Bean Validation. It’s a server-side valdr add-on which parses your domain model for Bean Validation constraint annotations and builds the JSON document required by valdr. This means AngularJS will effectively use the same constraints on the front-end as your JEE application uses on the back-end.

  • Jonathan Etaix

    Hi, your demo link is bad :/