Override AngularJS Default Email Validator

Issue

I want to override email validator of AngularJS. I want it to use my custom string, to validate email address.
The code I found in their documentation is like this:
JS:

   var app = angular.module('registrationApp', []);

    app.directive('overwriteEmail', function() {
      var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;

      return {
        require: 'ngModel',
        restrict: '',
        link: function(scope, elm, attrs, ctrl) {
            if (ctrl && ctrl.$validators.email) {

                // this will overwrite the default Angular email validator
                ctrl.$validators.email = function(modelValue) {
                    return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
                }
            }
        }
    }
});

HTML:

<div data-ng-app="registrationApp" data-ng-init="">
  <form name="form" class="css-form" novalidate>
  <div>
      Overwritten Email:
      <input type="email" ng-model="myEmail" overwrite-email name="overwrittenEmail" />
      <span ng-show="form.overwrittenEmail.$error.email">This email format is invalid!     </span><br>
      Model: {{myEmail}}
    </div>
  </form>
</div>

But the code does not work. The error thrown is:

TypeError: Cannot read property ’email’ of undefined
at link (http://localhost:63342/goga_tests/js/registration.js:39:32)
at N (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:54:372)
at g (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:47:256)
at g (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:47:273)
at N (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:54:313)
at g (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:47:256)
at N (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:54:313)
at g (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:47:256)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:46:377
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js:18:314

Thanks in advance for help!

Solution

angular version 1.2.26 that you are using does not add $validators special property on the ngModel controller instance. You need 1.3.x version of angular.

Provided you have 1.3.x you can just use your directive as is, and you can add priority 2 to be greater than ng-model (which is 1) so that your directive sets the validator before ng-model directive takes its turn :

app.directive('overwriteEmail', function() {
  var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;

  return {
    require: 'ngModel',
    restrict: '',
    priority: 2,
    link: function(scope, elm, attrs, ctrl) {
      if (ctrl && ctrl.$validators.email) {
        // this will overwrite the default Angular email validator
        ctrl.$validators.email = function(modelValue) {
          return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
        }
      }
    }
  }
});

Demo

var app = angular.module('app', []);

app.directive('overwriteEmail', function() {
  var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;

  return {
    require: 'ngModel',
    restrict: '',
    priority: 1,
    link: function(scope, elm, attrs, ctrl) {
      if (ctrl && ctrl.$validators.email) {
        // this will overwrite the default Angular email validator
        ctrl.$validators.email = function(modelValue) {
          return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
        }
      }
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<div ng-app="app">
  <div>
    <form name="form" class="css-form" novalidate>
      <div>
        Overwritten Email:
        <input type="email" ng-model="myEmail" overwrite-email name="overwrittenEmail" />
        <span ng-show="form.overwrittenEmail.$error.email">This email format is invalid!     </span>
        <br>Model: {{myEmail}}
      </div>
    </form>
  </div>
</div>

You can also stick with using ng-pattern and use form.overwrittenEmail.$error.pattern to display the message if invalid pattern.

<input type="email" ng-pattern="/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i" 
                    ng-model="myEmail" name="overwrittenEmail" />
   <span ng-show="form.overwrittenEmail.$error.pattern">

Demo

var app = angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div>
    <form name="form" class="css-form" novalidate>
      <div>
        Overwritten Email:
        <input type="email" ng-model="myEmail" ng-pattern="/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i" name="overwrittenEmail" />
        <span ng-show="form.overwrittenEmail.$error.pattern">This email format is invalid!     </span>
        <br>Model: {{myEmail}}
      </div>
    </form>
  </div>
</div>

Answered By – PSL

Answer Checked By – Mildred Charles (AngularFixing Admin)

Leave a Reply

Your email address will not be published.