How to Validate Emails in Angular

Validating emails in Angular is essential to ensure the accuracy and completeness of provided addresses. Without performing validation, dead-end email accounts can clog your application and complicate your interaction with users.

Fortunately, Angular offers comprehensive mechanisms for validating users’ emails and ensuring their accuracy. 

Email Validation in Angular

Angular provides several ways of validating emails, some of which are mentioned below:

  • Built-in validation: Angular comes with some built-in email validators you can use to ensure the correctness and completeness of user-provided email addresses.
  • Pattern validation: This allows you to specify a regular expression (regex) Angular email validation pattern that should match the user-provided value before validation can occur.
  • Custom validation: You can also create your own custom email validators, especially if the built-in validators do not match your specific use case.

In this Angular email validation tutorial, we’ll see how you can use these validation criteria to enhance the accuracy of user-provided email accounts.

How to Create Email Fields in Angular

Just like any other form element, Angular offers two different techniques for creating emails and processing the user input: reactive and template-driven. 

Although the two approaches allow you to create intuitive email fields and embed them in your application, they differ in philosophies and programming styles. For the rest of this tutorial, we’ll assume that you have some basic knowledge of how to use the two form modules.

Now, let’s start getting our hands dirty…

Angular Email Validation Project Setup

At the end of this tutorial, this is what we want to achieve:

Let’s start by installing the Angular CLI, which we’ll use to create a simple application for illustrating how to validate emails in Angular.

Here is the code to run on the command line interface:

npm install -g @angular/cli

Then, let’s use the CLI to create a simple application where users can input their email addresses:

ng new email-validation-tutorial

Here is the structure of our email validation project on the Visual Studio Code editor:

To assist us in displaying useful validation and error messages to users, we’ll include the Bootstrap CSS framework in our project. We’ll add the Bootstrap CDN in the index.html file, inside the <head>

Bootstrap comes with super-handy classes we can use to provide real-time feedback to users and assist them in providing accurate inputs. Remember that you can also create your own custom CSS classes to help in displaying error messages to users.

Next, in the app.component.html file, let’s remove the default code and replace it with the following code for the email fields:

<!--app.component.html-->
<div class="container-fluid">
<form>
  <h2>Please provide your email address</h2>
 
	<div class="form-group">
  	<label>Primary Email:</label>
  	<input type="email" class="form-control" />
	</div>

	<div class="form-group">
  	<label>Secondary Email:</label>
  	<input type="email" class="form-control" />
	</div>
</form>
</div>

Here is how the email fields look on a browser:

As you can see on the code above, we’ve just used HTML together with some Bootstrap classes to create the simple email form fields. We’ll start adding some Angular code in the next steps.

Creating Reactive Forms in Angular

In Angular reactive forms, the component class is the main source of truth. Therefore, rather than implementing validation via attributes in the template—just like in template-driven situations—the validator functions are included in the form control model of the component class. This way, Angular can call these validators anytime there is a change in the value of the form control.

To add reactive capabilities to the email field, inside the app.module.ts file, let’s import ReactiveFormsModule from the @angular/forms package and specify it in the imports array.

Here is the code:

//app.module.ts
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
  imports: [
    //other imports here
    ReactiveFormsModule
  ],
//more code here
})
export class AppModule { }

The FormGroup and the FormControl classes are some of the fundamental blocks for defining reactive forms in Angular applications. Therefore, we’ll import them inside the app.component.ts file. A form group is essential for monitoring the form’s validity status and changes in its child FormControl instances. 

To create a new FormGroup instance, we’ll define a constructor in the AppComponent class; it’ll have an object of named keys that are mapped to their control. 

The first argument passed in the FormControl constructor sets the initial value of the form element. In this case, we specified the initial values as empty strings to make the email fields to appear empty on the UI.  

So far, here is the code for the app.component.ts file:

//app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'email-validation-tutorial';
  userEmails = new FormGroup({
	primaryEmail: new FormControl(''),
	secondaryEmail: new FormControl('')
  });  

}

Next, let’s associate the FormGroup model with its view to create a communication layer between the two components.

Here is the updated code for the app.component.html file.

<!--app.component.html-->
<div class="container-fluid">
<form [formGroup]="userEmails">

  <h3>Please provide your email addresses</h3>

  <div class="form-group">
	<label>Primary Email:</label>
	<input type="email" class="form-control" formControlName="primaryEmail" />
  </div>
 
  <div class="form-group">
	<label>Secondary Email:</label>
	<input type="email" class="form-control" formControlName="secondaryEmail" />
  </div>

</form>

</div>

Consequently, the form control and the DOM can interact with one another: any changes in the model are reflected in the view, and vice versa.

Reactive Forms Validation of Emails

To validate emails created using the reactive forms approach, we’ll follow these three steps:

  • Apply validation rules to the email form controls
  • Provide visual validation feedback to users
  • Display form validation error messages

1. Apply validation rules

To access Angular’s built-in email validators, we need to use the Validators class. The validator function can process the value of a FormControl and determine whether the validation criteria has passed or not.

Let’s import Validators in the app.component.ts file.

//app.component.ts
import { Validators } from '@angular/forms';
//more code here

Since we want to make use of Angular’s sync validators, which are functions that process a control instance and instantly give the validation results, we’ll pass them as the second argument in the instantiation of the FormControl constructors. Also, since we want to use multiple validators, we’ll pass the functions as an array.

In this case, we’ll use the required() and the pattern()validators. The required() validator will ensure that the control for the email input field is not empty and the pattern() validator will ensure that the control’s value matches the specified regex pattern.

Here is the regex Angular email validation pattern:

"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"

Here is the app.component.ts file with the email validators included.

//app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'email-validation-tutorial';
  userEmails = new FormGroup({
	primaryEmail: new FormControl('',[
  	Validators.required,
  	Validators.pattern("^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$")]),
	secondaryEmail: new FormControl('',[
  	Validators.required,
  	Validators.pattern("^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$")])
  });  

}

2. Provide visual feedback to users

The second step in email validation in controller is to provide real-time visual feedback to users that something is not right.

Since Angular mirrors several form control properties onto the control elements in terms of CSS classes, we can utilize these classes to add some styling to the form control elements that reflect the changes in the state of the form—and display useful visual feedback to users. 

For example, we can use the .ng-invalid and the .ng-touched classes to check whether an input element is invalid and whether a user has visited the element, respectively. For this tutorial, we’ll use the properties associated with the class names. 

Let’s display a red border to each of the form controls when the form validation status is invalid; that is, when validation has failed.

In the app.component.html file, let’s bind the Bootstrap’s class.is-invalid class to the input elements and tie it to the condition that the email fields should be invalid and touched. We’ll also use the getter method to get access to the specific form controls.

<!--app.component.html-->

	<input [class.is-invalid] = "userEmails.get('primaryEmail').invalid && userEmails.get('primaryEmail').touched"
	type="email" class="form-control" formControlName="primaryEmail" />
 
<!--more code here-->

	<input [class.is-invalid] = "userEmails.get('secondaryEmail').invalid && userEmails.get('secondaryEmail').touched"
	type="email" class="form-control" formControlName="secondaryEmail" />

So, if we click inside any of the email fields and navigate away, the red border appears—indicating that the form control state is both invalid and touched.

Here is the screenshot:

3. Display validation error messages

The last step is displaying real-time error messages to users so that they can correct any problems with the provided email addresses.

To make our code short and easy to read, let’s create a getter method that returns a form control, in the app.component.ts file. This way, we can conveniently access the primary email field using primEmail instead of userEmails.get('primaryEmail') and the secondary email field using secondEmail instead of userEmails.get('secondaryEmail'). 

//app.component.ts

//more code here
export class AppComponent {

  get primEmail(){
	return this.userEmails.get('primaryEmail')
  }

  get secondEmail(){
	return this.userEmails.get('secondaryEmail')
  }

//more code here  

}

In the app.component.html file, let’s add the div element that will assist in displaying error messages conditionally to users. We’ll use the *ngIf directive to conditionally render this element if the email field is invalid, has been touched, or has been provided with a value (is dirty).

Then, within the div tag, let’s create separate error messages for each rule we defined in the first step above. To display the error messages conditionally to users, let’s use the form’s errors object with the *ngIf directive. We’ll check if the errors object exists and then access the required or pattern property. 

Here is the code:

<!--app.component.html-->

  	<div *ngIf="(primEmail.invalid && primEmail.touched) || primEmail.dirty">
    	<small *ngIf="primEmail.errors?.required" class="text-danger">Primary email is required</small>
    	<!--question mark(?) is a safe navigation operator-->
    	<small *ngIf="primEmail.errors?.pattern" class="text-danger">Please provide a valid email address</small>
  	</div>
 
<!--more code here-->  

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

So, if a user enters an invalid email address in the form, an appropriate message will be displayed to them. The error message will disappear whenever the validation conditions are passed.

Here is a video illustration:

Wrapping up the code

Here is the entire code we used in creating this reactive form validation example in Angular.

<!--index.html-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Email Validation Tutorial</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
	integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>

<body>
  <app-root></app-root>
</body>

</html>
<!--app.component.html-->
<div class="container-fluid">
  <form [formGroup]="userEmails">

	<h3>Please provide your email addresses</h3>

	<div class="form-group">
  	<label>Primary Email:</label>
  	<input [class.is-invalid]="primEmail.invalid && primEmail.touched" type="email" class="form-control"
    	formControlName="primaryEmail" />

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

	</div>

	<div class="form-group">
  	<label>Secondary Email:</label>
  	<input [class.is-invalid]="secondEmail.invalid && secondEmail.touched" type="email" class="form-control"
    	formControlName="secondaryEmail" />

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

	</div>

  </form>

</div>
//app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  get primEmail(){
	return this.userEmails.get('primaryEmail')
  }

  get secondEmail(){
	return this.userEmails.get('secondaryEmail')
  }

  title = 'email-validation-tutorial';
  userEmails = new FormGroup({
	primaryEmail: new FormControl('',[
  	Validators.required,
  	Validators.pattern("^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$")]),
	secondaryEmail: new FormControl('',[
  	Validators.required,
  	Validators.pattern("^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$")])
  });  

}
//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [
	AppComponent
  ],
  imports: [
	BrowserModule,
	ReactiveFormsModule //added
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Creating Template-Driven Forms in Angular

As we mentioned earlier, Angular also provides a template-driven approach for creating forms. Since template-driven forms manage the logic solely in the template, there is no direct access to the FormControl instance for passing the email validation in controller—like in reactive forms. Therefore, we’ll need to include a directive in the template for performing the email form validation.

First, let’s learn how template-driven forms can be created in Angular.

In the app.component.html file, let’s clear the existing code and leave the markup for creating the two email fields. 

<!--app.component.html-->
<div class="container-fluid">
  <form>
	<h2>Please provide your email address</h2>

	<div class="form-group">
  	<label>Primary Email:</label>
  	<input type="email" class="form-control" />
	</div>

	<div class="form-group">
  	<label>Secondary Email:</label>
  	<input type="email" class="form-control" />
	</div>
  </form>
</div>

Then, in the app.module.ts file, let’s remove ReactiveFormsModule and replace it with FormsModule

Here is the code:

//app.module.ts
import { FormsModule } from '@angular/forms';
@NgModule({
  imports: [
    //other imports here
    FormsModule
  ],
//more code here
})
export class AppModule { }

To track the cumulative value of the form and its validation status, we’ll need to define the NgForm directive in a template variable by utilizing ngForm as the key. Consequently, this allows us to access several underlying user interaction properties of the FormGroup instance—such as valid and untouched—which are replicated on the directive itself. 

To associate the child controls of the email fields with the form, let’s apply the NgModel directive with a name attribute. This directive creates a FormControl instance, which monitors the value, user activities, as well as other validation status of the control, ensuring the model is synced with the view.

Next, to bind the user-provided form data to a model, let’s generate a model class called UserData by running the following code on the command line interface:

ng generate class userData

Then, in the in the user-data.ts file, let’s add some properties to the UserData class.

//user-data.ts
export class UserData {
	constructor(
	public primaryAddress: string,
	public secondaryAddress: string
	){}
}

To create an instance of the created model, let’s update the app.component.ts file with the new property. After creating an instance of the model, it’s now possible to use two-way binding to bind the userModel data to the email form.

Here is the updated app.component.html file:

<!--app.component.html-->
<div class="container-fluid">
  <form #usersEmail="ngForm">
	<h2>Please provide your email address</h2>

	<div class="form-group">
  	<label>Primary Email:</label>
  	<input type="email" class="form-control" name="primaryEmail" [(ngModel)]="userModel.primaryAddress" />
	</div>

	<div class="form-group">
  	<label>Secondary Email:</label>
  	<input type="email" class="form-control" name="secondaryEmail" [(ngModel)]="userModel.secondaryAddress" />
	</div>

  </form>
</div>

Template-Driven Forms Validation of Emails

Just like we validated the reactive forms, we’ll follow the following three steps for validating template-driven email forms in Angular:

  • Apply validation rules to the email form controls
  • Provide visual validation feedback to users
  • Display form validation error messages

1. Apply validation rules

In this case, let’s use the built-in Angular RequiredValidator and the PatternValidator directives to confirm the accuracy of the provided email addresses.

To use the RequiredValidator directive, we’ll simply add the required attribute to the form input controls. This will check whether the control is empty and returns the validation results. 

Secondly, to use the PatternValidator directive, we’ll simply add the pattern attribute to the form input controls. This will check whether the input value matches with the stipulated regex pattern.

Here is the regex Angular email validation pattern:

"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"

Here is the updated app.component.html file:

<!--app.component.html-->

  	<input type="email" required pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" class="form-control"
    	name="primaryEmail" [(ngModel)]="userModel.primaryAddress" />

<!--more code here-->

  	<input type="email" required pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" class="form-control"
    	name="secondaryEmail" [(ngModel)]="userModel.secondaryAddress" />

2. Provide visual feedback to users

Providing visual feedback is a great way of enhancing the experience of users when filling out forms. In this second step, we’ll validate the form fields and apply some CSS classes to visually indicate to users that their inputs are invalid—just as we did with reactive forms.

To access the NgModel properties for tracking the validity and state of the form controls, let’s create a template variable that refers to it.

Next, let’s bind the Bootstrap’s class.is-invalid class to the input elements and tie it to the condition that the email fields should be invalid and touched.

Here is the updated app.component.html file:

<!--app.component.html-->

  	<input type="email" #firstEmail="ngModel"
    	[class.is-invalid]="firstEmail.invalid && firstEmail.touched" required
    	pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" class="form-control" name="primaryEmail"
    	[(ngModel)]="userModel.primaryAddress" />

<!--more code here-->

  	<input type="email" #secondEmail="ngModel"
    	[class.is-invalid]="secondEmail.invalid && secondEmail.touched" required
    	pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" class="form-control" name="secondaryEmail"
    	[(ngModel)]="userModel.secondaryAddress" />

Consequently, if we click inside any of the email fields and navigate away, a red border appears—indicating that the form control state is both invalid and touched. 

3. Display validation error messages

Lastly, let’s display real-time error messages to assist users in correcting any anomalies with their provided email addresses.

Let’s add the div element that will assist in displaying error messages conditionally to users. We’ll use the *ngIf directive to conditionally render this element if the email field has errors, is invalid or has been touched.

Then, within the div tag, let’s create different error messages for each rule we defined in the first step above. To render the messages conditionally, let’s use the form’s errors object with the *ngIf directive. We’ll check if the errors object exists and then access the required or pattern property. 

Here is the code:

<!--app.component.html-->

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

<!--more code here-->

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

So, if a user enters an invalid email address in the form, an appropriate message will be displayed to them. The error messages will disappear whenever the validation conditions are passed.

Here is a video illustration:

Wrapping up the code

Here is the entire code we used in creating this template-driven form validation example in Angular.

<!--index.html-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Email Validation Tutorial</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
	integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>

<body>
  <app-root></app-root>
</body>

</html>
<!--app.component.html-->
<div class="container-fluid">
  <form #usersEmail="ngForm">
	<h2>Please provide your email address</h2>

	<div class="form-group">
  	<label>Primary Email:</label>
  	<input type="email" #firstEmail="ngModel" [class.is-invalid]="firstEmail.invalid && firstEmail.touched" required
    	pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" class="form-control" name="primaryEmail"
    	[(ngModel)]="userModel.primaryAddress" />

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

	</div>

	<div class="form-group">
  	<label>Secondary Email:</label>
  	<input type="email" #secondEmail="ngModel" [class.is-invalid]="secondEmail.invalid && secondEmail.touched"
    	required pattern="^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" class="form-control" name="secondaryEmail"
    	[(ngModel)]="userModel.secondaryAddress" />

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

  </form>
</div>
//app.component.ts
import { Component } from '@angular/core';
import { UserData } from './user-data';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
 
  title = 'email-validation-tutorial';
  userModel = new UserData('','')
 
}
//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
	AppComponent
  ],
  imports: [
	BrowserModule,
	FormsModule
    
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
//user-data.ts
export class UserData {
	constructor(
	public primaryAddress: string,
	public secondaryAddress: string
	){}
}

Conclusion

That’s how you can validate emails created using either the reactive approach or the template-driven approach in Angular and ensure their completeness and accuracy. You may also be interested in how to send emails with Angular app. Read our dedicated blog post for details.