'Angular 5 - form validation e-mail

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?



Solution 1:[1]

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"

Solution 2:[2]

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>

Solution 3:[3]

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

Solution 4:[4]

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-.]+$')
    ]))
});

Solution 5:[5]

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.

Solution 6:[6]

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;
}`

Solution 7:[7]

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!

Solution 8:[8]

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="[email protected]" 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>

Solution 9:[9]

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>
        

Solution 10:[10]

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>

Solution 11:[11]

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;
  }
}

Solution 12:[12]

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 :)