Custom validation – Reactive Form (using function) in Angular

In Angular, there are some validation standards in Validators module, but in real applications they won’t be enough so we need to define some other validations to make sure the form is filled exactly as what client need.
Here you can find a sample of custom validator for test the email entered is unique and passwords (2 fields) are match.

Reactive-form.html

<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
   <input type="text" formControlName="email" [ngClass]="{ 'is-invalid': submitted && f.email.errors }" />
   <div class="invalid-feedback">
      <div>Email is required</div>
      <div>not a valid email address</div>
      <div>Email already exists</div>
   </div> 
   <input type="password" formControlName="password" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
   <div class="invalid-feedback">
      <div>Password is required</div>
      <div>min 6 characters</div>
   </div> 
   <input type="password" formControlName="confirmPassword" [ngClass]="{ 'is-invalid': submitted && f.confirmPassword.errors }" />
   <div class="invalid-feedback">
      <div>Confirm Password is required</div>
      <div>Passwords must match</div>
   </div> 
   <button>Register</button> 
</form>


Reactive-form.ts

import { Component, OnInit} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MustMatch, uniqueUser } from './custom-valid.validator';

export class ReactiveFormComponent implements OnInit {
  registerForm: FormGroup;
  submitted = false;
  constructor(private formBuilder: FormBuilder) { }
  ngOnInit() {
      this.registerForm = this.formBuilder.group({
          firstName: ['', Validators.required],
          lastName: ['', Validators.required],
          email: ['', [Validators.required, Validators.email]],
          password: ['', [Validators.required, Validators.minLength(6)]],
          confirmPassword: ['', Validators.required]
      }, {
          validator: [MustMatch('password', 'confirmPassword'), uniqueUser('email')]
      });
  }

  get f() { return this.registerForm.controls; }
  onSubmit() {
      this.submitted = true;
      if (this.registerForm.invalid) {
          return;
      }
      console.log(JSON.stringify(this.registerForm.value))
  }
}


custom-valid.validator.ts

import { FormGroup } from '@angular/forms';
import { promise } from 'protractor';
import { resolve } from 'q';

export function MustMatch(controlName: string, matchingControlName: string) {
    return (formGroup: FormGroup) => {
        const control = formGroup.controls[controlName];
        const matchingControl = formGroup.controls[matchingControlName];
        if (matchingControl.errors && !matchingControl.errors.mustMatch) {
            return;
        }

        if (control.value !== matchingControl.value) {
            matchingControl.setErrors({ mustMatch: true });
        } else {
            matchingControl.setErrors(null);
        }
    }
}

export function uniqueUser(controlName: string) {
    const db = ['a@a.a', 'b@a.a'];
    return (formGroup: FormGroup) => {
        const control = formGroup.controls[controlName];
        if (control.errors && !control.errors.uniqueUser) {
           return;
        }
        if (db.indexOf(control.value) != -1) {
            control.setErrors({ uniqueUser: true });
        } else {
            control.setErrors(null);
        }
    }
}

Leave a Reply

Your email address will not be published.