Creating a Custom Async Validator in Angular using Reactive Forms

MyValidators.ts

import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs/Observable';

export class MyValidators {
  static forbiddenNames(control: FormControl): { [s: string]: boolean } {

    const forbidden = ['Mahmood', 'Reza', 'Ahmad'];

    if (forbidden.indexOf(control.value) !== -1) {
      return {'nameIsForbidden': true};
    }

    return null;
  }

  static forbiddenEmails(control: FormControl): Promise<any> | Observable<any> {
    const promise = new Promise<any>(((resolve, reject) => {
      setTimeout(() => {
        if (control.value === '[email protected]') {
          resolve({'emailIsForbidden': true});
        } else {
          resolve(null);
        }
      }, 1500);
    }));

    return promise;
  }
}

app.component.ts

import {Component, OnInit} from '@angular/core';
import {FormArray, FormControl, FormGroup, Validators} from '@angular/forms';
import {MyValidators} from './MyValidators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  genders = ['male', 'female'];
  signupForm: FormGroup;

  ngOnInit(): void {
    this.signupForm = new FormGroup({
      'userData': new FormGroup({
        'username': new FormControl(null, [Validators.required, MyValidators.forbiddenNames]),
        'email': new FormControl(null, [Validators.required, Validators.email],
          [MyValidators.forbiddenEmails])
      }),
      'gender': new FormControl('male'), // default value for radiobutton => male
      'hobbies': new FormArray([])
    })
    ;
  }

  onSubmit() {
    console.log(this.signupForm);
  }

  onAddHobby() {
    const newControl = new FormControl(null, Validators.required);
    (<FormArray>this.signupForm.get('hobbies')).push(newControl);
  }

}