Angular 5 email & compare password validation, different ways

angular 5 confirm password validation angular 5 password match validation password and confirm password validation in angular 5 angular2 password confirmation angular 4 password validation ionic 2 confirm password validation angular 5 email pattern, angular 5 email custom directive angular 2 password validation pattern

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?

  • c.value: if control value is null (null, "", undefined) return null (no validation)
  • if not match our pattern then return an object of having error name say "pattern" true
  • if everything pass, return null

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

Ali Adravi 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.
  • Angular-5
  • angularjs
  • custom-directive
  • compare-validation
By Ali Adravi On 23 Jan, 18  Viewed: 10,305

Other blogs you may like

angular 5 form validation easiest way

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: 2,392

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 2

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: 17,427

Custom Directives in AngularJS with example and demo

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: 3,886

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 1

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: 28,855

Angularjs Progress bar directive for entire application

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: 13,095