How can I simplify form validation in angularJS?

The code below seems to work pretty well for doing basic "required" form validation.

The form displays a red Name is required message when the field is dirty + invalid and a Great! message if the field is dirty + valid.

But it's a mess having repeat this code for each and every field in the form:

<form name="myForm">
    <div class="control-group" 
     ng-class="{error: myForm.name.$invalid && myForm.name.$dirty}">
        <label>Name:</label>
        <input type="text" name="name" ng-model="user.name" required/>
        <span ng-show="myForm.name.$invalid && myForm.name.$dirty" 
            class="help-inline">Name is required</span>
        <span ng-show="myForm.names.$valid && myForm.names.$dirty">Great!</span>
    </div>
</form>

I would like to be able to specify the ng-show and ng-class attributes in some easier way.

One way you could do it is to abstract your validation expression to scope methods:

PLUNKER

HTML:

<div class="control-group" ng-class="{error: isInvalid('name')}">
  <label>Name:</label>
  <input type="text" name="name" placeholder="Name" ng-model="user.name" required/>
  <span ng-show="isInvalid('name')" class="help-inline">Name is required</span>
  <span ng-show="isValid('name')">Great!</span>
</div>

Controller:

function Ctrl($scope) {
  $scope.isInvalid = function(field){
    return $scope.myForm[field].$invalid && $scope.myForm[field].$dirty;
  };

  $scope.isValid = function(field){
    return $scope.myForm[field].$valid && $scope.myForm[field].$dirty;
  };

}

I know the question is old but I want to share with the world my awesome new angular directive, I made a project on Github and I think that it just rocks compare to whatever is/was available...I based myself on the excellent Laravel PHP Framework and made it available under Angular... Enough said, let's give some examples:

<!-- example 1 -->
<label for="input1">Simple Integer</label>
<input type="text" validation="integer|required" ng-model="form1.input1" name="input1" />

<!-- example 2 -->
<label for="input2">Alphanumeric + Exact(3) + required</label>
<input type="text" validation="alpha|exact_len:3|required" ng-model="form1.input2" name="input2" />

So I can define whatever amount of validation rules which I want in a simple directive validation="min_len:2|max_len:10|required|integer" and the error message will always display in the next <span> Don't you guys like it already? 1 line of code for your input, 1 line of code for the error display, you can't be simpler than that...oh and I even support your custom Regex if you want to add :)

No more clustered Form with 10 lines of code for 1 input when the only thing you need is 2 lines, no more, even for an input with 5 validators on it. And don't worry about the form not becoming invalid, I took care of that as well, it's all handled the good way.

Take a look at my Github project Angular-Validation and spread the word =)

EDIT
To make an even more smoother user experience, I added validation on timer. The concept is simple, don't bother the user while he's busy typing but do validate if he makes a pause or change input (onBlur)... Love it!!!
You can even customize the timer as per your liking, I've decided to default it to 1 second within the directive but if you want to customize you can call as for example typing-limit="5000" to make a 5 sec. timeout. Full example:

<input type="text" validation="integer|required" typing-limit="5000" ng-model="form1.input1" name="input1" />


EDIT #2
Also added input match confirmation validation (ex.: password confirmation), here is a sample code

<!-- input match confirmation, as for example: password confirmation -->
<label for="input4">Password</label>
<input type="password" name="input4" ng-model="form1.input4" validation="alpha|min_len:4|required"  />
<label for="input4c">Password Confirmation</label>
<input type="password" name="input4c" ng-model="form1.input4c" validation="match:form1.input4,Password|required"  />

EDIT #3
Refactored the directive so that the requirement of having a <span> to display the error is unnecessary, the directive now handles it by itself, see the code change reflected on top.

DEMO
Added a live demo on Plunker

You can use Angular-Validator.

It will:

  1. Display the required error message in red (optionally with bootstrap classes)
  2. Mark the field as invalid if it does not pass the validator
  3. Prevent the form from being submitted while it is invalid
  4. Only show the message if the field is dirty
  5. Clean up your code!

It will not

  1. Display the success message (support for success messages is coming soon).

Example

<form name="myForm" angular-validator> <div class="control-group"> <label>Name:</label> <input type="text" name="name" ng-model="user.name" required-message="'Name is required'" required/> </div> </form>

A work around for showing the success message

<form name="myForm" angular-validator> <div class="control-group"> <label>Name:</label> <input type="text" name="name" ng-model="user.name" required-message="'Name is required'" required/> <span ng-show="myForm.names.$valid && myForm.names.$dirty">Great!</span> </div> </form>

For more use cases and examples see: https://github.com/turinggroup/angular-validator

Disclaimer: I am the author of Angular-Validator

Please use this css

    <style type="text/css">
.myForm input.ng-invalid.ng-dirty {
    background-color: #FA787E;
}

.myForm input.ng-valid.ng-dirty {
    background-color: #78FA89;
}
</style>

There is an angular directive/project on github called xtForm. It looks like its off the a good start to simply angular field validation. XtForm reduces the amount of validation message markup after your input tags.

Link to demo site https://github.com/refactorthis/xtform

small usage example. No extra markup(ng-show on spans) needed to get this field is required error message/tool tip.

<form xt-form novalidate>
  <input name="email" ng-model="modelVal" xt-validate required>
  <button type="submit">Submit</button>
</form>

Consider using this ngValidate module I have been working on.

<input name="demo-field-1" ng-model="user.name" ng-validate="customStrategy">

The directive will add a span to hold your error messages. You can define custom validation strategies and individual error messages.

ngValidateFactory.strategies.customStrategy = [
{
    value:ngValidate.required;
    message:"This field is required"
},
{
    value:[ngValidate.minLength,8];
    message:"Minimum 8 characters are required"
},
{
    value:[myFunction,arg1,arg2];
    message:"This field fails my custom function test"
}]

demo plnkr

Try this HTML:

<form name="myForm" ng-submit="submitForm()" novalidate>

            <!-- NAME -->
            <div class="form-group" ng-class="{'has-error' : myForm.name.$invalid && !myForm.name.$pristine }">
                <label>Client Name</label>
                <input type="email" name="email" class="form-control" ng-model="formValues.userName" required placeholder="User Name">
                <p ng-show="myForm.email.$invalid && !myForm.email.$pristine" class="error">Your email is required.</p>
            </div>


            <div class="form-group">
                <label >Password</label>
                <input type="password" name="formValues.password" class="form-control" placeholder="Password" ng-model="formValues.password" ng-maxlength="6" required>
            </div>
            <div class="form-group">
                <label>Confirm Password</label>
                <input type="password" name="formValues.confirmPassword"  class="form-control"  placeholder="Confirm Password" ng-model="formValues.confirmPassword" required>
                <span class="error" ng-if="formValues.confirmPassword" ng-show="formValues.password!=formValues.confirmPassword">password should not match</span>
            </div>

            <div class="form-group">
                <label>First Name</label>
                <input type="text" name="formValues.firstName"  class="form-control" placeholder="First Name" ng-model="formValues.firstName" ng-keyup="acceptAlphabets(formValues.firstName,$event)" required>
                <span class="error"  ng-show="myString">Accept only letters</span>
                <span class="error" ng-show="myStringLength">Accept only 50 characters</span>
            </div>

            <div class="form-group">
                <label>Last Name</label>
                <input type="text" name="formValues.larstName" class="form-control"  placeholder="Last Name" ng-model="formValues.larstName" required>

            </div>
            <div class="form-group">
                <label>Date Of Birth</label>
                <input type="text" name="formValues.dateOfBirth" class="form-control" id="exampleInputPassword1" placeholder="Date Of Birth" ng-model="formValues.dateOfBirth" ng-keyup="dateFun(formValues.dateOfBirth,$event)" required>
                <span class="error" ng-show="dateVal">Incorrect Format, should be MM/DD/YYYY</span>

            </div>

            <button type="submit" class="btn btn-primary" ng-disabled="myForm.$invalid" ng-model="formValues.submit">Submit</button>

        </form>