Creating a reusable validation directive

Loading

In AngularJS, directives are powerful tools used to create reusable components and behavior. A common use case for directives is to implement custom form validation logic. By creating a reusable validation directive, you can modularize your form validation, making it easier to apply and maintain across different parts of your application.

Objective

We will create a reusable validation directive in AngularJS that checks whether an input field contains a valid email address. This directive will be reusable, allowing it to be used with different input fields and forms across the application.

Steps to Create a Reusable Validation Directive

1. Create the Directive in AngularJS

First, we’ll define a new directive called validEmail. This directive will use a custom validation function to check if the value in the input field is a valid email address.

2. HTML Structure for the Form

Here’s an example form where we will use the validEmail directive for the email input field.

<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="FormController">
<form name="myForm" ng-submit="submitForm()" novalidate>
<label for="email">Email:</label>
<input type="email" name="email" ng-model="email" valid-email />

<div ng-show="myForm.email.$invalid && myForm.email.$dirty">
<span>Email is invalid.</span>
</div>

<br/><br/>
<button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>
</div>
</body>
</html>

3. Define the AngularJS Module and Controller

Now, we’ll define an AngularJS module named myApp and a controller FormController to handle the form submission.

angular.module('myApp', [])
.controller('FormController', function($scope) {
// Function to handle form submission
$scope.submitForm = function() {
if ($scope.myForm.$valid) {
alert("Form submitted successfully!");
} else {
alert("Please correct the form errors before submitting.");
}
};
});

4. Create the Custom Validation Directive

In the directive, we will define the custom validation for the email field using AngularJS’s $validators. This will ensure that our custom validation logic is reusable and can be applied to multiple fields across different forms.

angular.module('myApp')
.directive('validEmail', function() {
return {
require: 'ngModel', // This directive will require the ngModel controller
link: function(scope, element, attrs, ngModel) {
// Custom email validation
ngModel.$validators.validEmail = function(value) {
if (value) {
// Basic email validation regex
var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
return emailPattern.test(value);
}
return true; // If the value is empty, validation is passed
};
}
};
});

5. Explanation of the Code

Directive Definition (validEmail)

  • require: 'ngModel': This ensures that the directive has access to the ngModel controller of the element. The ngModel is used to bind the value of the input field and manage the validation state.
  • link function: The link function is where we implement the directive’s behavior. It is called when the directive is attached to an element in the DOM. This is where we define the validation logic for the email.

Custom Validation Logic (ngModel.$validators.validEmail)

  • ngModel.$validators.validEmail: We define a custom validator by adding it to the $validators object of the ngModel. This validator will be executed whenever the value of the input field changes.
  • Email Validation Regex: We use a regular expression (emailPattern) to validate if the value entered in the input field is a valid email format. If it matches the regex, the validator returns true, indicating the validation passed. Otherwise, it returns false.
  • Empty Field Handling: If the field is empty, we return true, meaning the validation passes (as we are only validating the email format when there is a value).

Validation in the Form (ng-show)

In the HTML form, we use ng-show to display an error message if the email field is invalid and has been touched by the user (i.e., it’s been interacted with).

6. Reusability of the Directive

This directive is reusable in multiple forms. All you need to do is use the valid-email attribute on any input field you want to validate. Here’s another example:

<form name="myForm" ng-submit="submitForm()">
<label for="email1">Email 1:</label>
<input type="email" name="email1" ng-model="email1" valid-email />

<label for="email2">Email 2:</label>
<input type="email" name="email2" ng-model="email2" valid-email />

<button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>

Both email1 and email2 will be validated using the same validEmail directive.

7. Extending the Directive for More Complex Validation

You can easily extend this directive to handle more complex validation scenarios. For example, you could modify the directive to accept custom validation patterns or even allow for asynchronous validation (e.g., checking if the email is already taken).

angular.module('myApp')
.directive('validEmail', function($http) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$validators.validEmail = function(value) {
if (value) {
var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
return emailPattern.test(value);
}
return true;
};

// Example of asynchronous email validation
ngModel.$asyncValidators.emailTaken = function(modelValue, viewValue) {
var value = modelValue || viewValue;
return $http.get('/check-email', { params: { email: value } })
.then(function(response) {
if (response.data.exists) {
return $q.reject('Email is already taken');
}
return true;
});
};
}
};
});

Leave a Reply

Your email address will not be published. Required fields are marked *