Me gustaría implementar un validador de campos cruzados async que obtenga algunos resultados de mi backend.
Aquí está la parte relevante del componente:
export class MemberComponent implements OnInit { private _form: FormGroup = new FormGroup({ activity: new FormControl(null), account: new FormControl(null), role: new FormControl(null), fare: new FormControl(null), info: new FormControl(null), }, { validators: new ValidateMemberNotTaken(this._memberService) }); constructor(private _memberService: MemberService){} ...Aquí está mi implementación del validador:
export class ValidateMemberNotTaken implements AsyncValidator { constructor(private memberService: MemberService) {} validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> { const {activity, account, role} = control.value; return this.memberService.exists(activity,account,role).pipe( map(exists => (exists ? { memberExists: true } : null)), catchError(() => of(null)) ); } } y aquí está la función que exists utilizada en mi validador:
@Injectable({ providedIn: 'root' }) export class MemberService { private _apiUrl = 'http://localhost:3000/api/members'; constructor( private _http: HttpClient, ) { } exists(activityId: number, accountId: number, roleId: number): Observable<boolean> { const url = `${this._apiUrl}/activity/${activityId}/account/${accountId}/role/${roleId}`; return this._http.get<boolean>(url); } }Al compilar mi código, me sale el siguiente error:
Error: src/app/components/member/member.component.ts:31:6 - error TS2345: Argument of type '{ validators: ValidateMemberNotTaken; }' is not assignable to parameter of type 'ValidatorFn | ValidatorFn[] | AbstractControlOptions'.¿Es posible implementar validadores asíncronos de campos cruzados? Si es así, ¿podría decirme qué está mal con mi código?
No sé por qué está creando una clase del Validador, generalmente usamos funciones para validadores personalizados (async y sync) y eso es lo que sugeriría:
export function validateMemberNotTaken(memberService): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { if (control) { const {activity, account, role} = control.value; return memberService.exists(activity,account,role).pipe( map(exists => (exists ? { memberExists: true } : null)), catchError(() => of(null)) ); } return of(null); }; }Importe la función y luego marque el validador de la siguiente manera en su grupo de formulario:
validators: validateMemberNotTaken(this._memberService)