Custom reactive form validation using Angular

1Create your custom methods:

In ReactiveForm you have to options to validate data:

  • Validating FormGroup: validate all the form (example: isPassowrdCorrect)
  • Validating FromControl: validate a specific form control (example: isValueStartWithY)

The following code have two validation functions

  1. isPassowrdCorrect: test if the password and the password2 values are equal
  2. isValueStartWithY: test if the value of the selected control starts with an Y
import { FormGroup, FormControl } from "@angular/forms";

//validating form group
export function isPassowrdCorrect(control: FormGroup): { [s: string]: boolean }{
    if(control.value.password==null || control.value.password2==null || control.value.password=='' || control.value.password2=='' || control.value.password2!==control.value.password){
        return {'isPasswordInvalid': true};
    }
    return null;
}

//validating form control
export function isValueStartWithY(control: FormControl): { [s: string]: boolean }{
    if(control.value==null || !control.value.startsWith("Y")){
        return {'isValueNotStartWith': true};
    }
    return null;
}
  • If the value is valid you should return null
  • isValueNotStartWith and isPasswordInvalid are the errors name like required

2Create your component and your form groups and controls:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { isPassowrdCorrect, isValueStartWithY } from '../validations/validation';

@Component({
  selector: 'app-yami-code-validation',
  templateUrl: './yami-code-validation.component.html',
  styleUrls: ['./yami-code-validation.component.css']
})
export class YamiCodeValidationComponent implements OnInit {

  yamicodeForm: FormGroup;

  constructor() { }

  ngOnInit() {
    this.yamicodeForm = new FormGroup({
      'password': new FormControl(''),
      'password2': new FormControl(''),
      'name': new FormControl('', [isValueStartWithY.bind(this)]),
    }, [isPassowrdCorrect.bind(this)]);
  }

  save() {
    if (this.yamicodeForm.valid) {
      alert("data is valid");
    }
  }

}

3Show errors and validations in html:

<form (submit)="save()" [formGroup]="yamicodeForm">
  <div>
    <input type="text" formControlName="name" name="name" placeholder="name">
    <ul class="myError" *ngIf="yamicodeForm.get('name').errors && (yamicodeForm.controls.name.dirty || yamicodeForm.controls.name.touched )">
      <li *ngIf="yamicodeForm.get('name').errors['isValueNotStartWith']">
        <p class="myError">Name sould start with Y</p>
      </li>
    </ul>
  </div>
  <div>
    <input type="password" formControlName="password" name="password" placeholder="Password">
  </div>
  <div>
    <input type="password" formControlName="password2" name="password2" placeholder="Repeat password">
    <ul class="myError" *ngIf="yamicodeForm.errors && ((yamicodeForm.controls.password.dirty || yamicodeForm.controls.password.touched) && (yamicodeForm.controls.password2.dirty || yamicodeForm.controls.password2.touched) )">
      <li *ngIf="yamicodeForm.errors['isPasswordInvalid']">
        <p class="myError">The passwords should not be null and should be identiques</p>
      </li>
    </ul>
  </div>
  <button type="submit" [disabled]="yamicodeForm.invalid">Save</button>
</form>

PS:

  • disabled: disable the form if it's invalid
  • yamicodeForm.errors: if the form have errors
  • yamicodeForm.errors['isPasswordInvalid']: if the form have the error isPasswordInvalid
  • yamicodeForm.get('name').errors: if the control name have errors
  • yamicodeForm.get('name').errors['isValueNotStartWith']: if the control name have the error isValueNotStartWith