46

I want to create a form where the user will enter his email. I'd like to validate email format client-side.

Is there any generic email validator in Angular 2?

NB: Something similar to AngularJS validator.

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Julien Alary
  • 780
  • 1
  • 5
  • 16

11 Answers11

77

You can do only using html:

<md-input-container class="md-icon-float md-block" flex-gt-sm>
    <label>Email</label>
        <input md-input
            id="contact-email"
            type="text"
            ngControl="email"
            #email="ngForm"
            [(ngModel)]="contact.email"
            required
            pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+$">

    <div class="md-errors-spacer" [hidden]="email.valid || email.untouched">
        <div class="md-char-counter" *ngIf="email.errors && email.errors.required">
            Email is required
        </div>
        <div class="md-char-counter" *ngIf="email.errors && email.errors.pattern">
            Email is invalid
        </div>
    </div>
</md-input-container>
Toolkit
  • 10,779
  • 8
  • 59
  • 68
Mush
  • 2,326
  • 2
  • 16
  • 22
  • 2
    I much prefer this approach to using a code based solution... thanks! – Jon Preece Apr 07 '16 at 01:36
  • 3
    FWIW, with new domain endings like .google, .bike. and many others the email validation pattern needs to be adjusted. This might be helpful: http://emailregex.com/ For JavaScript in HTML5 this is the pattern: ```pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"``` – Vitali Kniazeu Sep 21 '16 at 16:00
  • 1
    The pattern that worked for me was: pattern="^(\\w|[0-9.!#$%&’*+/=?^_\\`{|}~-])+@(\\w|[0-9-])+(?:[.](\\w|[0-9-])+)*$" notice that the double-backslashes. The pattern failed to work with only one backslash before each 'w'. The reason could be that this string lives inside the pattern property of @Component. Not sure though. – XDS Oct 22 '16 at 21:48
  • Trying to write RFC-compliant regular expressions for email can be insanely convoluted. People have been debating about this for years. I would suggest that the best regex would be one that checks for something before the @ symbol followed by something after it with a dot. Then follow up by sending an email verification to the address. This looks like: pattern=".+@.+\..+" – luvaas Feb 07 '17 at 07:39
  • my browser freezes when typing long emails, using this approach. The problem might be in regex itself. – eagor Apr 28 '17 at 08:35
  • ` ` not working :( i don't know why – Joe Sleiman May 12 '17 at 05:57
65

For angular 4 and above:

According to This you can use "email validator".

Example:

If you use template-driven forms:

<input type="email" name="email" email>
<input type="email" name="email" email="true">
<input type="email" name="email" [email]="true">

If you use model-driven forms(aka ReactiveFormsModule) use Validators.email:

this.myForm = this.fb.group({
    firstName: ['', [<any>Validators.required]],
    email: ['', [<any>Validators.required, <any>Validators.email]],
});

Old answer: You can use angular 2 FormGroup,

By using validators.pattern and regex like this:

 let emailRegex = '^[a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,15})$';
 this.myForm = this.fb.group({
        firstName: ['', [<any>Validators.required]],
        email: ['', [<any>Validators.required,  <any>Validators.pattern(emailRegex) ]],
 });
Asaf Hananel
  • 7,092
  • 4
  • 24
  • 24
  • 1
    not work ,always return false(but actually true when I run pattern.test('xxx')) – Daniel.Woo Nov 11 '16 at 07:48
  • @Daniel.Woo Maybe you can change the email regex to solve this problem? – Asaf Hananel Nov 13 '16 at 11:23
  • This seems to me the best answer. Using Validators.pattern is the best approach. Also the regex seems perfect. I have tried all the regex here: https://stackoverflow.com/questions/46155/validate-email-address-in-javascript but they don't really work for me. Just the regex in this answer works for me. – FrancescoMussi Nov 18 '16 at 11:31
  • This is the easiest method of email validation. You can wrap Validators.pattern(regexp) in a method call and then you end up with a custom validator. No point in reinventing the wheel every time. – Pierre Jan 26 '17 at 03:35
  • 2
    it's allowed, if am enter this format `ram.ram@ra`. it means it will be accept without dot (.) on the Email ID. – Ramesh Rajendran Mar 19 '17 at 21:00
49

You can use Form Directives and Control to do this.

export class TestComponent implements OnInit {
     myForm: ControlGroup;
     mailAddress: Control;

     constructor(private builder: FormBuilder) {
         this.mailAddress = new Control(
            "",
            Validators.compose([Validators.required, GlobalValidator.mailFormat])
        );
     }

     this.addPostForm = builder.group({
            mailAddress: this.mailAddress
     });
}

Import:

import { FormBuilder, Validators, Control, ControlGroup, FORM_DIRECTIVES } from 'angular2/common';

Then your GlobalValidator class:

export class GlobalValidator {

    static mailFormat(control: Control): ValidationResult {

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

        if (control.value != "" && (control.value.length <= 5 || !EMAIL_REGEXP.test(control.value))) {
            return { "incorrectMailFormat": true };
        }

        return null;
    }  
}

interface ValidationResult {
    [key: string]: boolean;
}

And then your HTML:

<div class="form-group">
    <label for="mailAddress" class="req">Email</label>
    <input type="text" ngControl="mailAddress" />
    <div *ngIf="mailAddress.dirty && !mailAddress.valid" class="alert alert-danger">
        <p *ngIf="mailAddress.errors.required">mailAddressis required.</p>
        <p *ngIf="mailAddress.errors.incorrectMailFormat">Email format is invalid.</p>
    </div>
</div>

For more information about this, you can read this good article : https://medium.com/@daviddentoom/angular-2-form-validation-9b26f73fcb81#.jrdhqsnpg or see this github project for a working example.

(edit : that reg ex does not seem to check for a dot in the domain

I use this one instead

/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

cfr http://emailregex.com/

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
AdrienTorris
  • 9,111
  • 9
  • 34
  • 52
  • One of the limitations of this is Angular2 doesn't still allows http requests in asynchrone validators. This issue is still open on github : https://github.com/angular/angular/issues/1068#issuecomment-183766054 – AdrienTorris Feb 18 '16 at 16:07
  • 1
    ATTENTION!!! Here the regular expression EMAIL_REGEXP is not properly constructed and it shows this mail as valid: "asd@f" – Just Shadow Jul 29 '16 at 13:35
  • 1
    @JustShadow technically that email address IS valid. The limitation to 5+ characters however is not coherent with this regex. – Sébastien Dec 05 '16 at 17:05
  • what's used in angular 2.4.1 for Control? – brabertaser19 Jan 04 '17 at 12:43
  • i could just add `email` to my input if i wouldn't care for `xxx@gmail` without `.com` being invalid – Toolkit Aug 28 '17 at 09:29
7

Here is another way of validating a field using RegEx. You can bind a method to the keyUp event of the field.

In your component:

import {NgForm} from 'angular2/common';

//...

emailValidator(email:string): boolean {
    var EMAIL_REGEXP = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

    if (!EMAIL_REGEXP.test(email)) {
        return false;
    }
    return true; 
}

In your HTML (view)

<div class="form-group">
    <label>Email address</label>
    <input type="email" class="form-control" [(ngModel)]="user.email"
           placeholder="Email address" required ngControl="email"
           #email="ngForm"
           (keyup)="emailValidator(email.value) == false ? emailValid = false : emailValid = true">
    <div [hidden]="emailValid || email.pristine" class="alert alert-sm alert-danger">Email address is invalid</div>
</div>

Another option (required field + validate when user leaves the field)

<div class="form-group">
    <label for="registerEmail">Email address</label>
    <input type="email" class="form-control" [(ngModel)]="user.email"
           placeholder="Email address" required ngControl="email"
           #email="ngForm"
           (blur)="emailValidator(email.value) == true ? emailIsInvalid = false : emailIsInvalid = true">
    <div [hidden]="email.valid || email.pristine" class="alert alert-sm alert-danger">This field is required</div>
    <div [hidden]="!emailIsInvalid" class="alert alert-sm alert-danger">Email address is invalid</div>
</div>

This method will work with any validation, so you could change the RegEx and validate Credit Card, Date, Time etc...

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
kbugala
  • 101
  • 3
  • 6
6

Yet another way to do this is using a custom directive. I like this approach as it's more consistent with the other ng2 validators.

import { Directive, forwardRef } from '@angular/core';
import { NG_VALIDATORS } from '@angular/forms';
import { Validator, AbstractControl } from '@angular/forms';


@Directive({
    selector: '[validateEmail][formControlName], [validateEmail][formControl],[validateEmail][ngModel]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: forwardRef(() => EmailValidator), multi: true }
    ]
})
export class EmailValidator implements Validator {

    constructor() {
    }

    validate(c: AbstractControl) {
        let EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;

        return EMAIL_REGEXP.test(c.value) ? null : {
            validateEmail: {
                valid: false
            }
        };


    }}

Then usage in html is

<input class="form-control" 
               type="email"
               [(ngModel)]="user.emailAddress" 
               name="emailAddress" 
               placeholder="first.last@example.com"
               validateEmail
Oliver
  • 1,490
  • 18
  • 19
  • it's allowed, if am enter this format `ram.ram@ra`. it means it will be accept without dot (.) on the Email ID. – Ramesh Rajendran Mar 19 '17 at 21:00
  • similar to https://blog.thoughtram.io/angular/2016/03/14/custom-validators-in-angular-2.html for anyone is searching for a full code example... and this one is good because it's inline on the html tag – petrosmm Dec 18 '20 at 17:45
4

I guess just now there is no email validator, but it's pretty easy to add a custom one. See this demo I used the same regex as angular1 uses.

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

  if (!EMAIL_REGEXP.test(control.value)) {
    return {invalidEmail: true};
  }
}
1

Also you can use ng2-validation-manager for reactive forms which makes validation match easier:

this.form = new ValidationManager({
  'email'       : 'required|email',
  'password'    : 'required|rangeLength:8,50'
});

and the view:

<form [formGroup]="form.getForm()" (ngSubmit)="save()">

    <div class="form-group">
      <label>Email</label>
      <input type="text" class="form-control" formControlName="email">
      <div *ngIf="form.hasError('email')" class="alert alert-danger">
        {{form.getError('email')}}
      </div>
    </div>

    <div class="form-group">
      <label>Password</label>
      <input type="password" class="form-control" formControlName="password">
      <div *ngIf="form.hasError('password')" class="alert alert-danger">
        {{form.getError('password')}}
      </div>
    </div>
    <button type="submit" class="btn btn-success">Submit</button>
</form>
Sabri Aziri
  • 4,084
  • 5
  • 30
  • 45
1

Update For Angular 4

ngOnInit() {
    this.user = new FormGroup({
        name: new FormGroup({
            firstName: new FormControl('',Validators.required),
            lastName: new FormControl('')
        }),
        age: new FormControl('',null,validate),
        email: new FormControl('',emailValidator),
    // ...
    });
}

Validator

export function emailValidator(control: AbstractControl):{[key: string]: boolean} {
    var EMAIL_REGEXP = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    if (control.value != "" && (control.value.length <= 5 || !EMAIL_REGEXP.test(control.value))) {
        return {invalid:true};
    }
    return null;
}

Template

<div class="row">
    <div class="col-md-12">
        <md-input-container>
            <input mdInput type="text" placeholder="Email" formControlName="email">
        </md-input-container>
    </div>
</div>
<div class="row">
    <div class="col-md-12">
        <span *ngIf="user.get('email').touched && !user.get('email').valid && !user.get('email').pristine">
            <small>Invalid email</small>
        </span>
    </div>
</div>
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Rahul Singh
  • 19,030
  • 11
  • 64
  • 86
1

You can use the built in Angular form validators without a form. I'm not sure if it's good practice, but it works.

const control = new FormControl('', Validators.email);
control.setValue(valueToCheck);
console.log(control.errors);

Other answers have already shown how to use it in a form:

this.contactUsForm = this.formBuilder.group({
      firstName: new FormControl('', Validators.required),
      lastName: new FormControl('', Validators.required),          
      emailAddress: new FormControl('', [Validators.required, Validators.email]),
      message: new FormControl('', Validators.required)
    });
0

I think nowadays you can use browser validation here. Email fields has a decent support and you can get validation result from element.validity.valid. You just need to pass this through the Angular custom validator

See https://developer.mozilla.org/en-US/docs/Web/API/ValidityState and http://caniuse.com/#feat=input-email-tel-url for details

s-f
  • 2,091
  • 22
  • 28
0

I'm using : https://www.npmjs.com/package/ng2-validation

npm install ng2-validation --save ng2-validation

I'm not responding exaclty your question but for a lot of common scenarios you can find a custom validator already implemented

example in your case : email : ['', [CustomValidators.email]]

Best Reagards,

Castelmager
  • 371
  • 3
  • 7