61

Am trying to validate an Email id field in angularJs using ng-pattern directive.

But am new to AngularJs. I need to show an error message as soon as the user enters the wrong email id.

The code which I have below is am trying to solve. Help me out with using ng-pattern for getting the proper result.

<script type="text/javascript" src="/Login/script/ang.js"></script>
<script type="text/javascript">
    function Ctrl($scope) {
        $scope.text = 'enter email';
        $scope.word = /^[a-z]+[a-z0-9._]+@[a-z]+\.[a-z.]{2,5}$/;
    }
</script>
    </head>
<body>
    <form name="myform" ng-controller="Ctrl">
        <input type="text" ng-pattern="word" name="email">
        <span class="error" ng-show="myform.email.$error.pattern">
            invalid email!
        </span>
        <input type="submit" value="submit">
    </form>
</body>

12 Answers12

68

If you want to validate email then use input with type="email" instead of type="text". AngularJS has email validation out of the box, so no need to use ng-pattern for this.

Here is the example from original documentation:

<script>
function Ctrl($scope) {
  $scope.text = 'me@example.com';
}
</script>
<form name="myForm" ng-controller="Ctrl">
  Email: <input type="email" name="input" ng-model="text" required>
  <br/>
  <span class="error" ng-show="myForm.input.$error.required">
    Required!</span>
  <span class="error" ng-show="myForm.input.$error.email">
    Not valid email!</span>
  <br>
  <tt>text = {{text}}</tt><br/>
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
  <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
  <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
</form>

For more details read this doc: https://docs.angularjs.org/api/ng/input/input%5Bemail%5D

Live example: http://plnkr.co/edit/T2X02OhKSLBHskdS2uIM?p=info

UPD:

If you are not satisfied with built-in email validator and you want to use your custom RegExp pattern validation then ng-pattern directive can be applied and according to the documentation the error message can be displayed like this:

The validator sets the pattern error key if the ngModel.$viewValue does not match a RegExp

<script>
function Ctrl($scope) {
  $scope.text = 'me@example.com';
  $scope.emailFormat = /^[a-z]+[a-z0-9._]+@[a-z]+\.[a-z.]{2,5}$/;
}
</script>
<form name="myForm" ng-controller="Ctrl">
  Email: <input type="email" name="input" ng-model="text" ng-pattern="emailFormat" required>
  <br/><br/>
  <span class="error" ng-show="myForm.input.$error.required">
    Required!
  </span><br/>
  <span class="error" ng-show="myForm.input.$error.pattern">
    Not valid email!
  </span>
  <br><br>
  <tt>text = {{text}}</tt><br/>
  <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
  <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
  <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
  <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
  <tt>myForm.$error.pattern = {{!!myForm.$error.pattern}}</tt><br/>
</form>

Plunker: https://plnkr.co/edit/e4imaxX6rTF6jfWbp7mQ?p=preview

SunnyMagadan
  • 1,819
  • 14
  • 12
  • 3
    i tried with this but while we use input type as email then it validates only that we enter content after @ rather than whwther it is alphabets or numerics – RandomUser Jun 30 '14 at 13:07
  • i need to use the pattern by keeping input type as text so that it'll check the content after @ in a mailid.. – RandomUser Jun 30 '14 at 13:10
  • 1
    i don't know whats wrong with your code, but i tried to use your approach with my example and it's work fine. you can test it here http://plnkr.co/edit/raac1Cywpa72nxZPmVk2?p=preview – SunnyMagadan Jun 30 '14 at 15:20
  • 6
    Angular's e-mail validation doesn't consider all the validation rules, e.g. two consecutive dots. The pattern has to be ^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$ – Marcos Lima Jun 25 '15 at 13:24
  • can i override the expression using $scope.email = "xyz expression" – Vikash Pandey Jan 13 '16 at 12:40
  • `$scope.email` will not work here, one example is `-` in the domain names, which the reg ex does not allow. – James Oravec Feb 22 '16 at 18:09
  • If you're using a custom directive knowing how to do this with ng-pattern would be useful, so this answer doesn't address the question. – Z2VvZ3Vp May 19 '16 at 19:51
  • Regex in your example does not allow numerics in domain name. – Xoyce Mar 13 '17 at 21:38
  • The angular "out of the box" validation just sux, it allows so many things that shouldnt be allowed !!! (e.g email like mail@mail - that makes no sense). If you want a proper way to validate emails, stick to ng-pattern. You should not advise people to use the out of the box thing there – DevMoutarde May 11 '17 at 09:05
54

There is nice example how to deal with this kind of problem modyfing built-in validators angulardocs. I have only added more strict validation pattern.

app.directive('validateEmail', function() {
  var EMAIL_REGEXP = /^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/;

  return {
    require: 'ngModel',
    restrict: '',
    link: function(scope, elm, attrs, ctrl) {
      // only apply the validator if ngModel is present and Angular has added the email validator
      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);
        };
      }
    }
  };
});

And simply add

<input type='email' validate-email name='email' id='email' ng-model='email' required>  
scx
  • 2,749
  • 2
  • 25
  • 39
  • 4
    {2,4} is wrong, extensions are up 5 characters, so {2,5} – ProxyGear Jul 03 '15 at 23:32
  • 7
    TLDs can be much longer than 5 characters! Longest is 24 according to http://data.iana.org/TLD/tlds-alpha-by-domain.txt – martinjbaker Nov 05 '15 at 11:24
  • If you are doing this in ASP.NET MVC Razor page, you may need to escape the `@` character in the regex, like so: `/^[_a-z0-9]+(\.[_a-z0-9]+)*@@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,5})$/` – Rosdi Kasim May 31 '17 at 18:30
  • 4
    Btw, in practise email should not be case sensitive (especially the domain name), therefore all `a-z` patterns should be replaced by `a-zA-Z`. – Rosdi Kasim May 31 '17 at 18:42
10

According to the answer of @scx ,I created a validation for GUI

app.directive('validateEmail', function() {
  var EMAIL_REGEXP = /^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/;
  return {
    link: function(scope, elm) {
      elm.on("keyup",function(){
            var isMatchRegex = EMAIL_REGEXP.test(elm.val());
            if( isMatchRegex&& elm.hasClass('warning') || elm.val() == ''){
              elm.removeClass('warning');
            }else if(isMatchRegex == false && !elm.hasClass('warning')){
              elm.addClass('warning');
            }
      });
    }
  }
});

And simply add :

css

.warning{
   border:1px solid red;
 }

html

<input type='email' validate-email name='email' id='email' ng-model='email' required>
vanduc1102
  • 5,769
  • 1
  • 46
  • 43
6

This is jQuery Email Validation using Regex Expression. you can also use the same concept for AngularJS if you have idea of AngularJS.

var expression = /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/;

Source.

Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
Ehtesham Shami
  • 125
  • 2
  • 7
3

You can use ng-messages

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-messages.min.js"></script>

include the module

 angular.module("blank",['ngMessages']

in html

<input type="email" name="email" class="form-control" placeholder="email" ng-model="email" required>
<div ng-messages="myForm.email.$error">
<div ng-message="required">This field is required</div>
<div ng-message="email">Your email address is invalid</div>
</div>
arun-r
  • 3,104
  • 2
  • 22
  • 20
3

Below is the fully qualified pattern for email validation.

<input type="text" pattern="/^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]*\.([a-z]{2,4})$/" ng-model="emailid" name="emailid"/>

<div ng-message="pattern">Please enter valid email address</div>
Pang
  • 9,564
  • 146
  • 81
  • 122
3

Now, Angular 4 has email validator built-in https://github.com/angular/angular/blob/master/CHANGELOG.md#features-6 https://github.com/angular/angular/pull/13709

Just add email to the tag. For example

  <form #f="ngForm">
    <input type="email" ngModel name="email" required email>
    <button [disabled]="!f.valid">Submit</button>
    <p>Form State: {{f.valid?'VALID':'INVALID'}}</p>
  </form>
so-random-dude
  • 15,277
  • 10
  • 68
  • 113
0

angularjs controller way, just an example to look for one or more email in the body of a message.

sp = $scope.messagebody; // email message body

if (sp != null && sp.match(/([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)\S+/)) {   
console.log('Error. You are not allowed to have an email in the message body');
}
Robot70
  • 600
  • 6
  • 10
0

I tried @Joanna's method and tested on the following websites and it didn't work.

  1. https://regex101.com/
  2. https://www.regextester.com/
  3. https://regexr.com/

I then modified it to and it worked.

/([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)\S+
Gagan
  • 49
  • 6
0

I have tried wit the below regex it is working fine.

Email validation : \w+([-+.']\w+)@\w+([-.]\w+).\w+([-.]\w+)*

subhashis
  • 4,629
  • 8
  • 37
  • 52
0

Spend some time to make it working for me.

Requirement:

single or comma separated list of e-mails with domains ending name.surname@gmail.com or team-email@list.gmail.com

Controller:

$scope.email = {
   EMAIL_FORMAT:  /^\w+([\.-]?\w+)*@(list.)?gmail.com+((\s*)+,(\s*)+\w+([\.-]?\w+)*@(list.)?gmail.com)*$/,
   EMAIL_FORMAT_HELP: "format as 'your.name@gmail.com' or comma separated 'your.name@gmail.com, my.name@list.gmail.com'"
};

HTML:

<ng-form name="emailModal">
    <div class="form-group row mb-3">
        <label for="to" class="col-sm-2 text-right col-form-label">
            <span class="form-required">*</span>
            To
        </label>
        <div class="col-sm-9">
            <input class="form-control" id="to"
                   name="To"
                   ng-required="true"
                   ng-pattern="email.EMAIL_FORMAT"
                   placeholder="{{email.EMAIL_FORMAT_HELP}}"
                   ng-model="mail.to"/>
            <small class="text-muted" ng-show="emailModal.To.$error.pattern">wrong</small>
        </div>
    </div>
</ng-form>

I found good online regex testing tool. Covered my regex with tests:

https://regex101.com/r/Dg2iAZ/6/tests

Dmitri Algazin
  • 3,332
  • 27
  • 30
-1

Use below regular expression

^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+)+((\.)[a-z]{2,})+$

It allows

test@test.com
test@test.co.in
test@test.gov.us
test@test.net
test@test.software
Ankur Raiyani
  • 1,509
  • 5
  • 21
  • 49