Angular email validation can be done in many different ways, by using the built-in directive, by using patterns or by creating custom directive. In this article we will try to see all the three different ways with working code in plunker. We will use our previous example and add three email text boxes to validate 1. by built-in directive, 2. by using pattern and finally we will write our own custom directive
To use the built-in directive please import EmailValidator
import { EmailValidator } from '@angular/forms';
Now add the validation code to our email property
email:["", [Validators.required, EmailValidator]]
Change the HTML to use this directive and show error message:
<div class='col-sm-6'>
<input type='text' formControlName='email' email
class='form-control'
placeholder='Email builin validator'>
<div *ngIf="email.invalid && (email.dirty || isSubmitted)" class="text-danger">
<div *ngIf="email.errors.required">Email is required.</div>
<div *ngIf="email.errors.email && !email.errors.required">Invalid email.</div>
</div>
</div>
Just added email
directive and change the error message, run and try to enter some text and email, take a breath.
Did you notice the problem, when you type any email without DOT it consider a valid email say just type a@b and it will show that this is a valid email. Do you think it is an issue, no, see the link on stackoverflow.com for more detail. If you want to validate the dot as well then we can try a pattern.
Email Pattern Validation
We need a pattern to test the entered email, so check the best patter or if you have any, create a variable `emailPattern' and assign the value to it:
emailPattern: string = /^(([^<>()\[\]\\.,;:\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,}))$/;
Note there is not quote at the beginning or at the end
Assign it to our emailp property:
emailp:["", [Validators.required, Validators.pattern(this.emailPattern)]],
When user will type and it is not valid then it will give the pattern error, so let's adjust the html to show the email pattern error
<div *ngIf="emailp.invalid && (emailp.dirty || isSubmitted)" class="text-danger">
<div *ngIf="emailp.errors.required">Email is required.</div>
<div *ngIf="emailp.errors.pattern && !emailp.errors.required">Invalid email.</div>
</div>
That's it run the code and check it, it will work smooth.
If you don't want to copy & paste the same pattern and add pattern validation and want to create the directive then let's create directive.
Email Validation Custom Directive
Before writing a validation directive, let's see what are the useful information already available.
Angular provide an interface Validator, which we can use for any validation directive:
interface Validator {
validate(c: AbstractControl): ValidationErrors | null
registerOnValidatorChange(fn: () => void)?: void
}
Not only this, they also provide a blue print of custom validation directive, it looks like this:
@Directive({
selector: '[custom-validator]',
providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]
})
class CustomValidatorDirective implements Validator {
validate(c: Control): {[key: string]: any} {
return {"custom": true};
}
}
Here is the link where I copy these code
We already have a blue print, we have pattern to check the email so let's go and use these information and convert our code in directive, here is the complete code
import { Directive } from '@angular/core';
import { Validator, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[advs-email]',
providers: [{provide: NG_VALIDATORS, useExisting: EmailDirective, multi: true}]
})
export class EmailDirective implements Validator {
emailPattern: string = /^(([^<>()\[\]\\.,;:\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,}))$/;
validate(c: Control): {[key: string]: any} {
if(c.value == null)
return null;
if(!this.emailPattern.test(c.value)){
return {"pattern": true};
}
return null;
}
}
If you will look code closely, you will notice, we have not added any magical things except the if and return, what is that and why?
To use our custom directive we need to import it in our app.module like this
import { EmailDirective } from './app/email.directive';
@NgModule({
.....
declarations: [ AppComponent, EmailDirective ],
.......
})
Remove rest of the code for clarity. Not time to user our directive in our HTML page
<input type='text' formControlName='emaild'
class='form-control' advs-email
placeholder='Email directive validatior'>
<div *ngIf="emaild.invalid && (emaild.dirty || isSubmitted)" class="text-danger">
<div *ngIf="emaild.errors.required">Email is required.</div>
<div *ngIf="emaild.errors.pattern && !emaild.errors.required">Invalid email( from directive).</div>
</div>
Compare Password Custom Directive
We have already created a custom directive for email validation so let's create one more for compare password.
Code is going to be very similar like email except one change that we need to get the value of another control to compare, let's see it.
To read the attribute we can use constructor and read the value by using control.root.get(attribute)
, here is the complete directive code of compare password:
import { Directive, Attribute } from '@angular/core';
import { Validator, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[advs-compare]',
providers: [{provide: NG_VALIDATORS, useExisting: CompareDirective, multi: true}]
})
export class CompareDirective implements Validator {
constructor(@Attribute('advs-compare') public comparer: string){}
validate(c: Control): {[key: string]: any} {
let e = c.root.get(this.comparer);
if(e && c.value !== e.value){
return {"compare": true};
}
return null;
}
}
Similar to email directive, register to app.module.ts file and use in html as advs-compare="password"
, password is the control to which we need to compare, see the complete html for verify password
<input type='password' formControlName='verify'
class='form-control'
advs-compare="password"
placeholder='Verify Password'>
<div *ngIf="verify.invalid && (verify.dirty || isSubmitted)" class="text-danger">
<div *ngIf="verify.errors.required">Verify Password is required.</div>
<div *ngIf="verify.errors.compare && !verify.errors.required">Password Mismatch.</div>
</div>
When I was testing I found an issue in compare directive and problem is that, when user type in password and then confirm password, till now everything is good till now. But if we change the password field, confirm password still show valid. To fix this we need to change our code a little bit more.
We need to know which control user is typing now, for that we can add one more property to password and confirm password, say parent='true' and 'false' respectively.
So we need to change our directive one more time, and now it will become to this:
import { Directive, Attribute } from '@angular/core';
import { Validator, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[advs-compare]',
providers: [{provide: NG_VALIDATORS, useExisting: CompareDirective, multi: true}]
})
export class CompareDirective implements Validator {
constructor(@Attribute('advs-compare') public comparer: string,
@Attribute('parent') public parent: string){}
validate(c: Control): {[key: string]: any} {
let e = c.root.get(this.comparer);
// value not equal in verify control
if (e && c.value !== e.value && !this.isParent) {
return {"compare": true};
}
// user typing in password and match
if (e && c.value === e.value && this.isParent) {
delete e.errors['compare'];
if (!Object.keys(e.errors).length) e.setErrors(null);
}
// user typing in password and mismatch
if (e && c.value !== e.value && this.isParent) {
e.setErrors({ "compare": true });
}
}
private get isParent() {
if (!this.parent)
return false;
return this.parent === 'true' ? true: false;
}
}
Note we added a private getter function isParent and check which control user is typing and remove the mismatch error of verify password when both match even if user is typing to the password (parent).
We need to add the directive in both text boxes password and verify password
// To password text box
advs-compare="verify" parent='true'
// To Verify Password text box
advs-compare="password" parent='false'
Now it is perfect, change the value here and there and it will work in every case.
That's what many users sent email, hope It will help. Feel free to comment and suggestion, if you have any better solution, post that.
See the previous article for more detail about validtion: angular 5 form validation easiest way
![]() |
Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
|
By Ali Adravi On 23 Jan, 18 Viewed: 16,513 |
Angular make form validation easier than ever, we are going to check with Angular FormBuilder, FormGroup and validation together in this article, We will also see how to validate email without writing any custom directive or any other code because it is already there. Some tricky way to show and... By Ali Adravi On 23 Jan 2018 Viewed: 3,705
Add/Edid Customer in Modal Popup --- In previous article we discussed how to search, delete and show detail of customer and contact list. In this article we will try to open the modal popup to add new customer and edit an existing customer record. I divided article in two parts because of the... By Ali Adravi On 29 Jul 2015 Viewed: 19,575
Angularjs custom directives are the common to avoid the duplicate code, it is easy powerful and really nice. There are already too many directive have been created by experts but as a developer we need to write our own to achieve our specific goal. ng-model, ng-if, ng-show, ng-repeat all these are... By Ali Adravi On 29 Jul 2015 Viewed: 4,488
Search sort Insert update and delete are the basic features we need to learn first to learn any language, In this article we will try to create these features with Web API, bootstrap modal popup and ui.router. We will use enetity framework code first to save and retrieve data from database. We... By Ali Adravi On 28 Jul 2015 Viewed: 31,336
Progress bar for Angularjs application by using directives is simple and real easy. I was googling and could not found any directive way, if you will check most of the people says before call the http method open the progress bas and close once you get the result or get any error. Do you think it... By Ali Adravi On 24 Jul 2015 Viewed: 14,197