<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular Form Validation Demo</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
<script src="controller.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body ng-app="FormValidationExample">
<div ng-controller="ctrlForm">
<form name="myForm" novalidate>
<div class="input-item">
<label for="txtEmail">Your email</label><br>
<input type="text" name="email" id="txtEmail" class="text-box" ng-model="email" email-regex required custom-focus />
<div class="error-wrapper" ng-show="myForm.email.$dirty && myForm.email.$invalid && !myForm.email.$focused">
<span ng-show="myForm.email.$error.required">Email is required</span>
<span ng-show="myForm.email.$error.emailregex">Please enter a valid email address</span>
</div>
</div>
<div class="input-item">
<label for="interests">What interests you?</label><br>
<textarea name="interests" id="interests" class="text-box" ng-model="interests" ng-maxlength="255" ng-minlength="10" required custom-focus></textarea>
<div class="error-wrapper" ng-show="myForm.interests.$dirty && myForm.interests.$invalid">
<span ng-show="myForm.interests.$error.maxlength">Must be less than 255 characters</span>
<span ng-show="myForm.interests.$error.minlength && !myForm.interests.$focused">Must be more than 10 characters</span>
</div>
</div>
<div class="input-item">
<label for="txtPets">How many pets do you have?</label><br>
<input type="number" min="0" pattern="-?\d*" name="pets" id="txtPets" class="text-box" ng-model="pets" required custom-focus />
<div class="error-wrapper" ng-show="myForm.pets.$dirty && myForm.pets.$invalid">
<span ng-show="myForm.pets.$error.required && myForm.pets.$dirty">Please enter 0 or more</span>
<span ng-show="myForm.pets.$error.number && myForm.pets.$dirty">Must be numeric</span>
<span ng-show="myForm.pets.$error.min && myForm.pets.$dirty">You can't have negative pets!</span>
<span ng-show="myForm.pets.$error.pattern && myForm.pets.$dirty">Must be an integer</span>
</div>
</div>
<!-- Bonus check-all demo! -->
<div class="input-item">
<label>What are you reading this for?</label>
<span class="inline-note" ng-show="checkedCount > 0">{{checkedCount}} selected</span><br>
<input type="checkbox" class="select-all" ng-model="checkboxes_motives.checked" ng-change="selectAllMotives(checkboxes_motives.checked)" /><br>
<input type="checkbox" name="motivation" id="play" ng-model="checkboxes_motives.items['play']"
ng-change="updateCheckedCount(checkboxes_motives.items['play'])" />
<label for="play">Play</label>
<br>
<input type="checkbox" name="motivation" id="work" ng-model="checkboxes_motives.items['work']"
ng-change="updateCheckedCount(checkboxes_motives.items['work'])" />
<label for="work">Work</label>
</div>
<input type="submit" value="Submit" ng-disabled="myForm.$invalid" />
</form>
</div>
</body>
</html>
.input-item {
margin: 18px 0;
}
.error-wrapper {
display: inline-block;
color: red;
}
.inline-note {
margin-left: 20px;
color: blue;
}
.text-box {
width: 200px;
}
.text-box.ng-valid:not(.custom-focused) {
border-color: green;
}
.text-box.ng-invalid.ng-dirty:not(.custom-focused) {
border-color: red;
}
Not only does Angular allow you to validate user input using built-in and custom directives, it also automatically furnishes your elements with helpful CSS classes.
Visit http://info.easydynamics.com/blog/angularjs-form-validation to learn about Angular form validation.
Visit http://info.easydynamics.com/blog/write-custom-angular-directives to learn how to write custom directives.
var myApp = angular.module('FormValidationExample', []);
myApp.controller('ctrlForm', ['$scope', function($scope) {
$scope.checkboxes_motives = { 'checked': false, items: {} };
$scope.choices = ['work', 'play'];
$scope.checkedCount = 0;
$scope.selectAllMotives = function(checked) {
angular.forEach($scope.choices, function (motive) {
var isChecked = $scope.checkboxes_motives.items[motive];
$scope.checkboxes_motives.items[motive] = checked;
if (checked != isChecked) {
$scope.updateCheckedCount(checked);
}
});
};
$scope.updateCheckedCount = function (checked) {
if (checked) $scope.checkedCount++;
else $scope.checkedCount--;
};
}]);
// Attaches event listeners
myApp.directive('customFocus', [function() {
var FOCUS_CLASS = "custom-focused"; //Toggle a class and style that!
return {
restrict: 'A', //Angular will only match the directive against attribute names
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
ctrl.$focused = false;
element.bind('focus', function(evt) {
element.addClass(FOCUS_CLASS);
scope.$apply(function() {ctrl.$focused = true;});
}).bind('blur', function(evt) {
element.removeClass(FOCUS_CLASS);
scope.$apply(function() {ctrl.$focused = false;});
});
}
}
}]);
// Adds custom validation test to element
myApp.directive('emailRegex', [function (ngModel) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, linkElement, linkAttributes, controller) {
var regex = /^[a-zA-Z0-9-\_]+[a-zA-Z0-9-_\.]*(\.[a-zA-Z0-9-_]+)*([a-zA-Z0-9]+)@[a-zA-Z]+[0-9a-zA-Z-\.]*[0-9a-zA-Z]+\.[a-zA-Z]{2,5}$/;
function checkValidity(value) {
var valid = true;
// This directive should consider an empty value to be valid
// because the required test, if specified, occurs separately
if (value != null && value.length > 0) {
valid = regex.test(value);
}
return valid;
}
controller.$parsers.unshift(function (value) {
// View to model
var valid = checkValidity(value);
// Note "emailregex" instead of "emailRegex" - should be all lowercase
// This allows "$error.emailregex" to work in the DOM
controller.$setValidity('emailregex', valid);
// Only return the value to the model if it's valid
return valid ? value : undefined;
});
controller.$formatters.unshift(function (value) {
// Model to view
controller.$setValidity('emailregex', checkValidity(value));
// Return the value regardless of validity,
// otherwise nothing will appear on the DOM
return value;
});
}
};
}]);