Retain Focus On Invalid Field Using AngularJS Custom Directive

Introduction

In this article I'll tell you about How to Retain Focus on Invalid Field using AngularJS Custom Directive.

Directives can be created for validation purpose but here I am not explaining those as some directives are already available for validation purpose, but you can download the source code and can get the directive from controller.js.

Let's see how to retain focus on invalid field through a simple application.

Step 1: Firstly, I created an HTML page where some controls are created and angular validation is applied. 

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>  
  5.     <script src="Controller.js"></script>  
  6. </head>  
  7. <body>  
  8.     <form ng-app="TestFormMod" name="ApplicantCustomerProfile" ng-controller="TestFormCtrl" novalidate angular-validator >  
  9.         <div class="gloabl-form-content">  
  10.               
  11.             <div class="row">  
  12.                 <div class="col yellow-divider">  
  13.                     <div class="col-first">  
  14.                         <label><span class="asterisk">*</span>Name of father/Guardian</label>  
  15.                     </div>  
  16.                     <div class="col-second">  
  17.                         <input name="guardian_or_father_name"  
  18.                             type="text"  
  19.                             name="fatherName"  
  20.                             ng-model="customer_profile.guardian_or_father_name"  
  21.                             validate-on="blur"  
  22.                             ng-pattern="/^[ a-zA-Z]*$/"  
  23.                             required  
  24.                             required-message="'Please enter father name.'"  
  25.                             invalid-message="'Only alphabets are allowed'"  
  26.                             maxlength="100" />  
  27.                     </div>  
  28.                     <div class="col-third">  
  29.                         <label>Name of Spouse</label>  
  30.                     </div>  
  31.                     <div class="col-four">  
  32.                         <input name="spouse_name" type="text" ng-model="customer_profile.spouse_name"  
  33.                             validate-on="blur"  
  34.                             ng-pattern="/^[ a-zA-Z]*$/"  
  35.                             invalid-message="'Only alphabets are allowed'"  
  36.                             maxlength="100" />  
  37.                     </div>  
  38.                 </div>  
  39.             </div>  
  40.             <div class="row">  
  41.                 <div class="col yellow-divider">  
  42.                     <div class="col-third">  
  43.                         <label><span class="asterisk">*</span>Phone Number</label>  
  44.                     </div>  
  45.                     <div class="col-four">  
  46.                         <input type="text"  
  47.                             name="annual_turnover"  
  48.                             ng-model="customer_profile.annual_turnover"  
  49.                             validate-on="blur"  
  50.                             ng-pattern="/^[ 0-9.]*$/"  
  51.                             required  
  52.                             required-message="'Please enter mobile number'"  
  53.                             invalid-message="'Only numbers are allowed.'" />  
  54.                     </div>  
  55.                 </div>  
  56.             </div>  
  57.   
  58.         </div>  
  59.     </form>  
  60. </body>  
  61. </html>  
  62. <style>  
  63.     input.apply-visited.ng-invalid:not(.apply-focus)  
  64.     {  
  65.         background-color: #ffeeee;  
  66.     }  
  67. </style>  

Here you can see that I had applied different kind of validation on three controls: required, number only, alphbets only.

You can see in the form tag that I had applied a directive named "angular-validator", this is the same directive which is used to apply the validations and you can get that from source code.

Step 2:

Now let's create a JavaScript file where controller will be created.

I created a controller named "TestFormCtrl", here you can write any code according to your requirements. 

  1. angular.module('TestFormMod', [])  
  2.   
  3. .controller('TestFormCtrl'function ($scope, $location, $rootScope) {  
  4.     //apply code here  
  5. })  

Step 3

After this I had created two directives which will help to retain focus on input fields. 

  1. .directive("parentDirective"function () {  
  2.     return {  
  3.         restrict: 'A',  
  4.         require: ['form'],  
  5.         controller: function () {  
  6.             // nothing here  
  7.         },  
  8.         link: function (scope, ele, attrs, controllers) {  
  9.             var formCtrl = controllers[0];  
  10.         }  
  11.     };  
  12. })  
  13.   
  14. .directive('input'function () {  
  15.     return {  
  16.         restrict: 'E',  
  17.         priority: -1000,  
  18.         require: ['^?parentDirective''^?angularValidator'],  
  19.         link: function (scope, elm, attr, ctrl) {  
  20.             if (!ctrl) {  
  21.                 return;  
  22.             }  
  23.   
  24.             elm.on('focus'function () {  
  25.                 elm.addClass('apply-focus');  
  26.   
  27.                 scope.$apply(function () {  
  28.                     ctrl.hasFocus = true;  
  29.                 });  
  30.             });  
  31.   
  32.             elm.on('blur'function () {  
  33.                 elm.removeClass('apply-focus');  
  34.                 elm.addClass('apply-visited');  
  35.   
  36.                 scope.$apply(function () {  
  37.                     ctrl.hasFocus = true;  
  38.                     ctrl.hasVisited = true;  
  39.   
  40.                 });  
  41.             });  
  42.   
  43.         }  
  44.     };  
  45. });  

First one is like a parent directive and second one will work only when we are having parent directive and validator directive. Second directive will help to retain focus on elements.

Now you just need to call this  directive in the form tag of your page.
  1. <form ng-app="TestFormMod" name="ApplicantCustomerProfile" ng-controller="TestFormCtrl" novalidate angular-validator parent-directive>  

Here I am only providing code for those conditions where user will not be able to move from one control to second unless he / she fulfills the validations, but if user click on button which is on master page and have some other controller then this code is not enough to stop the user from navigation. In that case you need to do modifications in your code and need to check whether page is valid or not, if not then you just need to stop the navigation as this code will be still working.

Output

Let's run the application and see the output.

On running the application three textbox will appear.


Now just click on required textbox and try to leave the textbox without filling the value.


Even if you enter the wrong value then also it will not allow you to leave the textbox.