19

i want to solve this problem: Angular 5 - template driven form

An input-field has type email. Example:

<input type="email" [(ngModel)]="model.email" #email="ngModel" email />

I want to validate this field. But it should not be a required field. The validation should only start, if it isn't empty. If the field is empty, everthing is fine. Otherwise an error message should be displayed until the e-mail adress is correct.

This is not realy working:

*ngIf="email.untouched && email.invalid"

So, how can i validate the email field? I miss a status like "not empty".

Any hint?

Igor
  • 60,821
  • 10
  • 100
  • 175
HansPeter
  • 319
  • 1
  • 4
  • 12
  • Have a look at https://stackoverflow.com/questions/25025102/angular-difference-between-pristine-dirty-and-touched-untouched – Safiyya Mar 08 '18 at 21:39
  • Thanks. I have an another Example: I fill the input field with some letters and delete it again.
    Dirty is true, Touched is true and valid is false. But in actual fact everythink is fine, because the input field is empty.
    – HansPeter Mar 08 '18 at 21:52
  • you can use angular inbuilt email validator. follow this link [here](https://angular.io/api/forms/EmailValidator) – Argon Jun 23 '18 at 05:08

13 Answers13

38

Use pattern attribute with a regular expression for email validation.

 <div class="form-group">
        <label for ="email">Email</label>
          <input type="text" class="form-control" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" id="email"name="email" ngModel #emailref="ngModel">
          <div *ngIf="emailref.errors &&(emailref.touched || emailref.dirty)" class ="alert alert-danger">
           <div [hidden]="!emailref.errors?.pattern">
             Invalid pattern
           </div> 
          </div> 
    </div>
Ahmad Sharif
  • 4,141
  • 5
  • 37
  • 49
Vikas
  • 11,859
  • 7
  • 45
  • 69
13

For Angular 8 versions there is inbuilt email validator available.

In component class variable

email= new FormControl('',[
    Validators.required,
    Validators.email
  ]);

In the component html

 <input type="email" [formControl]="email" class="form-control" id="email" required>
                    <div *ngIf="email.invalid && (email.dirty || email.touched)"
                    class="alert alert-danger">
                        <div *ngIf="email.errors.required">
                            Email is required.
                        </div>  
                        <div *ngIf="email.errors.email">
                            Please enter a valid email.
                        </div>                                               
                    </div> 
                       <div *ngIf="email.errors.email">
                            Please enter a valid email.
                        </div>   //this is not work
                       <div *ngIf="email.errors.validateEmail">
                            Please enter valid email
                        </div > //use this
Community
  • 1
  • 1
Krishnadas PC
  • 5,981
  • 2
  • 53
  • 54
5

You can simply pass additional condition into the ngIf directive to check if the current value of the input is empty string.

*ngIf="email.value !== '' && email.untouched && email.invalid"

Mateusz Witkowski
  • 1,646
  • 10
  • 24
2

I am using it in Angular 6+ and it's worked for me.

Use below pattern in TypeScript file.

this.validations_form = this.formBuilder.group({
    email: new FormControl('', Validators.compose([
           Validators.required,
           Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
    ]))
});
Ajay Gupta
  • 2,867
  • 23
  • 28
  • 1
    Nice, so much short... thing is Validators.email let pass email@email (whitout '.com' or so) – Tupac Feb 25 '21 at 12:49
2

Vikas gave a great answer! working instantly in the program, But the console is giving errors if you type/ handle other fields in the form (although still working) so I change #variable emailref to email, like this:

<div class="form-group">
  <input type="text" class="form-control" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" 
         id="email" name="email" ngModel #email="ngModel" placeholder="Email">
  <div *ngIf="email.errors &&(email.touched || email.dirty)" class="aler alert-danger">
    <div [hidden]="!email.errors?.pattern">
      Invalid pattern
    </div>
  </div>
</div>

So field attribute name="email" will be the same as the template variable #email.

barbsan
  • 3,418
  • 11
  • 21
  • 28
avivsab
  • 21
  • 4
2

in Angular 8:

<div class="form-group">
        <label for="email">Email</label>
        <input type="email" required id="email" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"
         ngModel #emailref="ngModel" class="form-control" [class.success]="!emailref.invalid">
         <div *ngIf="emailref.errors &&(emailref.touched || emailref.dirty)" class ="text-error">
              Invalid email
           </div>
       </div>

in your css file add these 2 simple classes

`.success{
border: 1px solid greenyellow;
}
.text-error{
    color: red;
}`
Erwin Draconis
  • 764
  • 8
  • 20
2

If you want to use Angular's built in email validator, even though it may not have the best RegEx (something like abc@abc will pass validation, but this is front-end so maybe you don't want to incur too much brain damage "solving" this), you need to add [email]="true" in your HTML template (nothing in your component.ts), like this:

<input type="email" name="email" #email="ngModel" [email]="true" [(ngModel)]="email_var">

Then, you can use *ngIf="email.errors?.email" to check its validity. According to Angular documentation, you can simply write email="true" or even just email, but [email]="true" makes it look official and less likely to be missed!

Jason
  • 657
  • 7
  • 13
1

I tried in angular 7

Below code in html works for me

<input type="email" class="form-control center-ele"
    [(ngModel)]="recruiter_mail" id="rmail"
    name="recriter_mail"
    pattern=".+@globex.com" size="30"
    #email="ngModel"
    [ngClass]="{ 'is-invalid': f.submitted && email.invalid }"
    required email
/>

<div *ngIf="f.submitted && email.invalid" class="invalid-feedback">
    <div *ngIf="email.errors.required">Email is required</div>
    <div *ngIf="email.errors.email">Email must be a valid email address</div>
</div>
SuperStar518
  • 2,814
  • 2
  • 20
  • 35
Ram
  • 11
  • 1
  • from your answer i am able to check validation for .com in email, is it possible to add both .com and .in? if so please help me – Bhrungarajni Apr 09 '20 at 06:56
1

I had a scenario where I wanted to enable a button and change its color in Angular 7 as soon as the email typed became valid:

import { fromEvent } from 'rxjs';
  
@ViewChild("emailInput") private emailInputRef: ElementRef;
isValidEmail = false; 
  
ngAfterViewInit(): void {
  fromEvent(this.emailInputRef.nativeElement, 'keyup')
  .subscribe(() => {
      var re = new RegExp("[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$");
      this.isValidEmail = re.test(this.emailInputRef.nativeElement.value);
  }); 
}
<mat-form-field style="width: 100%"> 
 <input #emailInput matInput placeholder="Email address*" type="email" autocomplete="offhack" style="width: 100%">
</mat-form-field>
<button [color]="isValidEmail ? 'accent' : ''" [disabled]="!isValidEmail" style="width: 100%" mat-flat-button>Send Verification Email</button>
        
leoncc
  • 233
  • 3
  • 6
0

Implement below in xyz.component.html file. This code will keep in mind of valid email and required email validation.

<mat-form-field>
         <input matInput #email="ngModel" type="email" [(ngModel)]="data.email" name="data_email" placeholder="Email" [class.is-invalid]="email.invalid && email.touched" required
                pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$">
         <mat-error *ngIf="email.errors && (email.invalid || email.touched) && email.errors.pattern">Please enter a valid email address.</mat-error>
         <mat-error *ngIf="email.errors && (email.invalid || email.touched) && email.errors.required">Email is required.</mat-error>
</mat-form-field>
am2505
  • 2,194
  • 15
  • 19
0

I think that the better answer for angular(6+) is the Ajay Gupta's one. Because Validators.email like Krishnadas's answer let pass things like email@email. But I searched for better patterns, and in this answer finded one that is so much better, and is explained.

And if you use a prettier, or something that formats your code (and is always better), your regex pattern is better to be between / / characters so:

this.form = this.formBuilder.group({
email: ['', [
       Validators.required,
       Validators.pattern(/^[\w]{1,}[\w.+-]{0,}@[\w-]{1,}([.][a-zA-Z]{2,}|[.][\w-]{2,}[.][a-zA-Z]{2,})$/)
       ]]
});

You can catch the errors like this:

<div *ngIf="(email.invalid && email.touched) || email.dirty">
    <small *ngIf="email.errors?.required" class="text-danger">email is required</small>
    <small *ngIf="email.errors?.pattern" class="text-danger">Please provide a valid email address</small>
</div>

You can make your own validators that extends Validators, to make your own email validator:

export class CommonValidators extends Validators {
  static email(control: FormControl): ValidationErrors | null {
    const value: string = control.value;
    if (_.isEmpty(value)) {
      return null;
    }

    const pattern = /^[\w]{1,}[\w.+-]{0,}@[\w-]{1,}([.][a-zA-Z]{2,}|[.][\w-]{2,}[.][a-zA-Z]{2,})$/;

    if (!value.match(pattern)) {
      return { email: true };
    }

    return null;
  }
}
Tupac
  • 647
  • 12
  • 37
0

The last year I was struggled for a good explaination to How can I validate an user email inserted from an input? Since I discovered the validator for angular, it was very simple, no pattern, no strange things just add Validators.email. For example :

email: new FormControl('', [Validators.required, Validators.email]),

It will do all the control for you :)

0

this also works:

<input type="email" name="email" ngModel email="true">
azizkale
  • 37
  • 2
  • 6