29

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.

5
  • I encapsulated this stuff in a directive. I also added the validation classes and spans using DOM manipulation. So my markup is just the label and input. Commented Jul 29, 2013 at 10:16
  • I know this is an old question, but i have written an Article that tries to solve this problem Commented Sep 11, 2013 at 8:58
  • You could try this angular module jonsamwell.github.io/angular-auto-validate - it takes the approach of reducing the complexity of the html expression to show/hide validation messages in favour of coded ones. Commented Jul 8, 2014 at 14:32
  • Another shameless self-promotion: johannesjo.github.io/ng-fab-form which has the advantage over angular-auto-validate, that it also displays nice globally configurable error messages, without requiring you to change any markup. Commented Dec 1, 2014 at 16:18
  • code.tutsplus.com/tutorials/… Commented Jan 5, 2018 at 11:25

11 Answers 11

36

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

}
Sign up to request clarification or add additional context in comments.

3 Comments

Nice idea, but how do I get the myForm reference (it's not in the scope, only the markup)? I've updated the html to provide more context.
myForm is automatically referenced. See this plnkr
You're right (I checked $scope in the wrong controller... duh). Thanks for answering my question!
8

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

1 Comment

Great directive. Thanks for taking care of this for me. :)
5

Please use this CSS

.myForm input.ng-invalid.ng-dirty {
    background-color: #FA787E;
}

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

Comments

4

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>

Check out more Angular-validator use cases and examples.

Disclaimer: I am the author of Angular-Validator

Comments

3

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>

1 Comment

Thanks for the tip Jeroen, "usage" of the module does help solve problem of simplifying the validation markup.
1

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

Comments

0

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>

Comments

0
<form ng-app="demoApp" ng-controller="validationCtrl" 
name="myForm" novalidate>

<p>Username:<br>
<input type="text" name="user" ng-model="user" required>
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Your Username is required.</span>
</span>
</p>

<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Your Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>

<p>Mobile:<br>
<input type="number" name="number" ng-model="number" required>
<span style="color:red" ng-show="myForm.number.$dirty && myForm.number.$invalid">
<span ng-show="myForm.number.$error.required">Your Phone is required.</span>
<span ng-show="myForm.number.$error.number">Invalid number.</span>
</span>
</p>

<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||  
myForm.email.$dirty && myForm.email.$invalid || myForm.number.$dirty && myForm.number.$invalid">
</p>
</form>

<script>
//This is controller
var app = angular.module('demoApp', []);
app.controller('validationCtrl', function($scope) {
    $scope.user = 'angular';
    $scope.email = '[email protected]';
});
</script>

Comments

0

I'm probably too late for the question, but you could use an external library to handle validation for you. Angular form validator (written by me) makes it easier by having few standard validators in place such as

  1. Required
  2. String (min/max length)
  3. Number (min/max value)
  4. Pattern
  5. Email
  6. Url
  7. Equal to (For verification of email / passwords)
  8. Custom (where you can plug in validation of your own)

And it allows to combine multiple validators to one field.

<form name="introform" ng-controller="intro">
    <div class="form-group" validator="required['Field is required'],string[5,20,'Should between 5 and 20 characters']">
        <label for="requiredField">Required Field</label>
        <input type="text" class="form-control" id="requiredField" name="requiredField"
               placeholder="Required Field" ng-model="model.requiredField">
    </div>
    <button type="submit" class="btn btn-default" ng-disabled="!introform.$valid">Submit</button>
</form>

Comments

0

Check out my angularJS form validaton on codpen link

I have showed an example how to validate required, minlength, maxlength, email, password case, confirm password match on my demo.

Here is the code:

var myApp = angular.module('myApp',[]);
myApp.controller('mainController',['$scope', function($scope) {
	
}]);
myApp.directive('validConfirmPassword', function() {
	return {
		require:'ngModel',
		link: function(scope, elem, attrs, ctrl) {
			ctrl.$parsers.unshift(function(viewValue, $scope) {
				var noMatch = viewValue != scope.myForm.password.$viewValue;
				ctrl.$setValidity('noMatch', !noMatch)
			})
		}
	}
})	
.content{ margin-top:50px;  }
.danger-text { color: red; }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
      <div class="container">
        <a class="navbar-brand" href="#">AngularJS Form Validation</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample07" aria-controls="navbarsExample07" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
    </nav>

	<div class="container content" ng-controller="mainController">
		<div class="row">
			<div class="col-sm-12">
				<form name="myForm" novalidate>
					<div class="row">
		    			<div class="col-md-6 mb-3">
							
								<label for="first_name">First Name</label>
								<input type="text" name="firstname" ng-model="firstname" id="firstname"  class="form-control" required>
								<p ng-show="myForm.firstname.$touched && myForm.firstname.$invalid" class="danger-text">Please enter your first name</p>	
							
						</div>
						<div class="col-md-6 mb-3">
							
								<label for="last_name">Last Name</label>
								<input type="text" name="last_name" ng-model="last_name" id="last_name"  class="form-control"  required>
								<p ng-show="myForm.last_name.$invalid && myForm.last_name.$touched" class="danger-text">Please enter your last name</p>
							
						</div>
					</div> <!-- End of row -->
					<div class="row">
						<div class="col-md-6 mb-3">
							<label for="username">Username</label>
							<input type="text" name="username" id="username" ng-model="username" class="form-control" ng-required="true" ng-minlength="4" ng-maxlength="10" >
							<p ng-show="myForm.username.$error.required && myForm.username.$touched" class="danger-text">Please enter username</p>
							<p ng-show="myForm.username.$error.minlength" class="danger-text">Username is too short</p>
							<p ng-show="myForm.username.$error.maxlength" class="danger-text">Username is too long</p>
						</div>
						<div class="col-md-6 mb-3">
							<label for="email">Email</label>
							<input type="email" name="email" id="email" class="form-control" ng-model="email">
							<p ng-show="myForm.email.$invalid && !myForm.email.$pristine" class="danger-text">Enter a valid email address</p>
						</div>
					</div> <!-- ENd of row -->
					<div class="row">
						<div class="col-md-6 mb-3">
							<label for="password">Password</label>
							<input type="password" class="form-control" id="password" name="password" ng-model="password" ng-minlength="8" ng-maxlength="20" ng-pattern="/(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])/" required  />
   <p class="danger-text" ng-show="myForm.password.$error.required && myForm.password.$touched">Password is required</p>
   <p class="danger-text" ng-show="!myForm.password.$error.required && (myForm.password.$error.minlength || myForm.password.$error.maxlength) && myForm.password.$dirty">Passwords must be between 8 and 20 characters.</p>
   <p class="danger-text" ng-show="!myForm.password.$error.required && !myForm.password.$error.minlength && !myForm.password.$error.maxlength && myForm.password.$error.pattern && myForm.password.$dirty">Must contain one lower &amp; uppercase letter, and one non-alpha character (a number or a symbol.)</p>
						</div> <!-- End of col md 6 -->
						<div class="col-md-6 mb-3">
							<label>Confirm Password</label>
							<input type="password" id="confirm_password" name="confirm_password" class="form-control" ng-model="confirm_password" valid-confirm-password required  />
   <p class="danger-text" ng-show="myForm.confirm_password.$error.required && myForm.confirm_password.$dirty">Please confirm your password.</p>
   <p class="danger-text" ng-show="!myForm.confirm_password.$error.required && myForm.confirm_password.$error.noMatch && myForm.password.$dirty">Passwords do not match.</p>
						</div>
					</div> <!-- ENd of row -->
					<div class="row">
						<div class="col-md-12">
							<button type="submit"  class="btn btn-primary">Submit</button>
						</div>
					</div>
				</form> <!-- End of form -->
			</div> <!-- End of col sm 12 -->
		</div> <!-- End of row -->
	</div> <!-- End of container -->
  </div>

Comments

-2

index.php

<form class="add-task" id="myForm" name="myForm" method="post" ng-submit="submitForm(myForm.$valid)" novalidate>
   <div class="form-actions">
      <!-- ng-patten for validation -->
      <span class="error" ng-show="myForm.username.$error.required">
      Required!</span> 
      <div class="input-group">
         <input type="text"  ng-model="user2.username"  name="username" ng-pattern="example.word" placeholder="User Name" required>
         <input  type="password"  ng-model="user2.password"   name="password" placeholder="user password" ng-minlength="4"
            ng-maxlength="10" required>
         <button class="btn btn-success" ng-show="displayadd" type="submit"  ng-click="addUser(user2)" ng-disabled="myForm.$invalid"><i class="glyphicon glyphicon-plus"></i> Add New user</button>
         <button class="btn btn-default" ng-show="displayupdate"  ng-click="updateUser(user2)" value="Update"ng-disabled="myForm.$invalid"><span class="glyphicon glyphicon-save"></span>Save Change</button>
         <p style="color:red" ng-show="myForm.password.$error.minlength" class="help-block">Password Is Very Short.</p>
         <p style="color:red"  ng-show="myForm.password.$error.maxlength" class="help-block">Password Is Very Long.</p>
      </div>
   </div>
</form>

In app.js include this function :

 $scope.submitForm = function() {
     if ($scope.myForm.$valid) {
         alert('Our Form Is Submited....');
     }
 };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.