在Angular FormControl上实现异步验证器



我遵循了Angular网站上关于创建异步验证器的简短指南,可以在这个url中找到。

https://angular.io/guide/form-validation implementing-a-custom-async-validator

因此,我得到了以下代码:
import { AsyncValidator, AbstractControl, ValidationErrors } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { CompanyService } from '../services/company/company.service';
@Injectable({ providedIn: 'root' });
export class UniqueCompanyNameValidator implements AsyncValidator {
constructor(private companyService: CompanyService) { }
validate(
ctrl: AbstractControl
): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return this.companyService.CheckName(ctrl.value).pipe(
map(isTaken => (isTaken ? { uniqueCompanyName: true } : null)),
catchError(() => of(null))
);
}
}

我如何添加到我的表单控件实际使用这个自定义验证器?我试图将验证器导入到我的组件中,然后将其添加到FormControl中,如以下代码所示,但得到了一个错误。

import { UniqueCompanyNameValidator } from '../../../shared/validators/custom.validators';
'company' : new FormControl(null, { validators: [Validators.required, Validators.minLength(2)], updateOn: 'blur' }, [UniqueCompanyNameValidator]),

我得到的错误如下:

Type 'typeof UniqueCompanyNameValidator' is not assignable to type 'AsyncValidatorFn'.
Type 'typeof UniqueCompanyNameValidator' provides no match for the signature '(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>'.
(alias) class UniqueCompanyNameValidator
import UniqueCompanyNameValidator

它必须是一个函数/验证器实例,而不是可注入的令牌(类/类型)。在您的示例中,要使其工作,您必须传递validate函数,而不是Service令牌。假设它是this.companyService,它就像

new FormControl(null, { validators: [Validators.required, Validators.minLength(2)], updateOn: 'blur' }, [this.comapnyService.validate.bind(this.companyService)]),

或者(我从不使用这个变体)

new FormControl(null, { validators: [Validators.required, Validators.minLength(2)], updateOn: 'blur' }, [this.comapnyService]),

我将创建一个ValidatorFn工厂方法,它将所需的服务作为参数,并从那里开始。

export class MyValidators{
static uniqueCompanyName(companyService:SompanyService){
return (ctrl:AbstractControl)=>{
return companyService.doCheCkeck(ctrl.value).pipe(
map(isTaken => (isTaken ? { uniqueCompanyName: true } : null))
);
}

}
}

'company' : new FormControl(null, { validators: [Validators.required, Validators.minLength(2)], updateOn: 'blur' }, [MyValidators.uniqueCompanyName(companyServiceInstance)]),

我必须承认你链接的指南对初学者是有误导的。你可以使用给定的服务来创建一个指令,它将注入UniqueAlterEgoValidator。

一样:

@Injectable({ providedIn: 'root' })
export class UniqueAlterEgoValidator implements AsyncValidator {
constructor(private heroesService: HeroesService) {}
validate(
ctrl: AbstractControl
): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return this.heroesService.isAlterEgoTaken(ctrl.value).pipe(
map(isTaken => (isTaken ? { uniqueAlterEgo: true } : null)),
catchError(() => of(null))
);
}
}
@Directive({
selector: '[myValidator]',
providers: [{provide: NG_VALIDATORS, useExisting: MyValidatorDirective , multi: true}]
})
export class MyValidatorDirective implements AsyncValidator {
constructor(private validator: UniqueAlterEgoValidator) {}
validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return this.validator.validate(control);
}
}

使用模板驱动的表单创建一个实现AsyncValidator的指令。
带有反应形式:创建一个返回AsyncValidatorFn的函数。

参见angular指南中关于自定义验证器的介绍。

最新更新