| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 
 | import { Component, OnInit } from "@angular/core";import {
 ControlValueAccessor,
 Validator,
 NG_VALUE_ACCESSOR,
 NG_VALIDATORS,
 NG_ASYNC_VALIDATORS,
 Validators,
 AbstractControl
 } from "@angular/forms";
 import { FormControl } from "@angular/forms";
 import { of } from "rxjs";
 import { filter, tap, map, delay, first } from "rxjs/operators";
 
 @Component({
 selector: "app-user",
 templateUrl: "./user.component.html",
 styleUrls: ["./user.component.css"],
 providers: [
 {
 provide: NG_VALUE_ACCESSOR,
 useExisting: UserComponent,
 multi: true
 },
 {
 provide: NG_ASYNC_VALIDATORS,
 useExisting: UserComponent,
 multi: true
 }
 ]
 })
 export class UserComponent implements OnInit, ControlValueAccessor, Validator {
 firstName = new FormControl("", [Validators.required], [this.asyncValidator]);
 onChange: (e) => {};
 onTouched: () => {};
 
 constructor() {}
 
 asyncValidator(c: AbstractControl) {
 return of(c.value === "123").pipe(
 delay(500),
 map(b => (b ? null : { nomatch: true }))
 );
 }
 
 ngOnInit() {
 this.firstName.valueChanges.subscribe({
 next: value => {
 if (this.onChange) {
 this.onChange(value);
 this.onTouched();
 }
 }
 });
 }
 
 writeValue(obj: any) {
 this.firstName.patchValue(obj);
 }
 
 registerOnChange(fn: any) {
 this.onChange = fn;
 }
 
 registerOnTouched(fn: any) {
 this.onTouched = fn;
 }
 
 validate() {
 return this.firstName.statusChanges.pipe(
 filter(status => status !== "PENDING"),
 map(status => this.firstName.errors),
 first()
 );
 }
 }
 
 
 |