使用 observables 时 angular 2 异步验证器中的 return
What to return in the angular 2 async validator when using observables
如果
我必须 return 在 customerNameValidator 中做什么
异步验证 fails/succeeds 我的 'customerName' FormControl 无效?
this.customerForm = this.formBuilder.group({
customerName:
[this.newCustomerName, [Validators.minLength(2), Validators.required],[this.customerNameValidator.bind(this)]]
});
customerNameValidator(c: AbstractControl)
{
return this.service.customerExists(c.value,this.companyId).subscribe(response =>
{
if(response == true)
{
alert("true");
}
else
{
alert("false");
}
});
}
您应该映射可观察对象以更改 returning 流的结果,而不是从中读取,而不是订阅。
customerNameValidator(c: AbstractControl)
{
return this.service.customerExists(c.value,this.companyId).map(response =>
{
if(response == true)
{
return { customerExists: true };
}
else
{
return;
}
});
}
返回值为 true 的对象是您应该 return observable 的方式。虽然您可能错过了异步验证器的一些重要步骤,但因为我们没有提供您的所有代码,所以很难说。 Try checking out this article or this article 获取更多信息。
我在 angular 6.1.1 上使用 AsyncValidatorFn 实现了反应式表单。并想分享我的一些学习
我发现 angular 不会像对内部同步验证器那样(自动)更新 AsyncValidatorFn 的表单控件。
因此,根据 "AsyncValidatorFn" 界面规范,您必须 "manually" 在
的实现中更新表单控件
(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
然后,您将检查 html 元素中的控件状态
我实现的是用户名存在性检查,这在用户注册过程中很常见
以下是代码摘录:
表单控件
// Supports alphabets and numbers no special characters except underscore('_') and dash('-') min 3 and max 20 characters.
this.userName = new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[A-Za-z0-9_-]{3,20}$')]),Validators.composeAsync([this.checkUser()]));
自定义异步验证器和辅助函数
checkUser (): AsyncValidatorFn{
return (c: AbstractControl): Observable<ValidationErrors> => {
return c
.valueChanges
.debounceTime(400)
.mergeMap(value => this.gabriel.filter({'userName':value}))
.map(stat => this.mapErr(c, stat));
}
}
private mapErr(c: AbstractControl, res: any): ValidationErrors{
let err: ValidationErrors;
switch (res['state']){
case 0:
err = null;
break;
case -100:
err = {'existed': true};
break;
case -1:
default:
err = {'failed': true};
}
c.setErrors(err);
return err;
}
注意我把控件作为参数输入到"mapErr"函数中,通过"c.setErrors(err);"设置控件。
"return err;" 声明 return "ValidationErrors" 根据 "AsyncValidatorFn" 接口规范。
"gabriel.filter()"使用提取的用户名查询后端;和 returns 0、-100、-1 分别对应 "ok"、"duplicated" 和 "operation failed"
filter(json): Observable<{}>{
let body = JSON.stringify(json);
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({ headers: headers });
return this.http.post(Cons.filter, body, options).timeout(10000).map((res:Response) => res.json());
}
控件签入html文件
<form [formGroup]="sf" (ngSubmit)="signin()">
<ion-item>
<ion-label>UserName</ion-label>
<ion-input type="text" formControlName="userName" [class.invalid]="userName.dirty&&userName.invalid&&userName.errors!=null" ></ion-input>
</ion-item>
<p *ngIf="userName.dirty && userName.hasError('existed')">
Username already existed
</p>
<p *ngIf="userName.dirty && userName.hasError('failed')">
can not check validity of Username
</p>
我还发现,在一个表单控件中满足同步验证器之前,不会触发异步验证器。
在我的例子中,我还使用了内置的 Validators.pattern 来定义最小长度为 3。(参见上面的用户名 formControl 定义)
只要我的输入长度小于 3,自定义异步验证器就不会触发。
如果
我必须 return 在 customerNameValidator 中做什么异步验证 fails/succeeds 我的 'customerName' FormControl 无效?
this.customerForm = this.formBuilder.group({
customerName:
[this.newCustomerName, [Validators.minLength(2), Validators.required],[this.customerNameValidator.bind(this)]]
});
customerNameValidator(c: AbstractControl)
{
return this.service.customerExists(c.value,this.companyId).subscribe(response =>
{
if(response == true)
{
alert("true");
}
else
{
alert("false");
}
});
}
您应该映射可观察对象以更改 returning 流的结果,而不是从中读取,而不是订阅。
customerNameValidator(c: AbstractControl)
{
return this.service.customerExists(c.value,this.companyId).map(response =>
{
if(response == true)
{
return { customerExists: true };
}
else
{
return;
}
});
}
返回值为 true 的对象是您应该 return observable 的方式。虽然您可能错过了异步验证器的一些重要步骤,但因为我们没有提供您的所有代码,所以很难说。 Try checking out this article or this article 获取更多信息。
我在 angular 6.1.1 上使用 AsyncValidatorFn 实现了反应式表单。并想分享我的一些学习
我发现 angular 不会像对内部同步验证器那样(自动)更新 AsyncValidatorFn 的表单控件。
因此,根据 "AsyncValidatorFn" 界面规范,您必须 "manually" 在
的实现中更新表单控件(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
然后,您将检查 html 元素中的控件状态
我实现的是用户名存在性检查,这在用户注册过程中很常见
以下是代码摘录:
表单控件
// Supports alphabets and numbers no special characters except underscore('_') and dash('-') min 3 and max 20 characters.
this.userName = new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[A-Za-z0-9_-]{3,20}$')]),Validators.composeAsync([this.checkUser()]));
自定义异步验证器和辅助函数
checkUser (): AsyncValidatorFn{
return (c: AbstractControl): Observable<ValidationErrors> => {
return c
.valueChanges
.debounceTime(400)
.mergeMap(value => this.gabriel.filter({'userName':value}))
.map(stat => this.mapErr(c, stat));
}
}
private mapErr(c: AbstractControl, res: any): ValidationErrors{
let err: ValidationErrors;
switch (res['state']){
case 0:
err = null;
break;
case -100:
err = {'existed': true};
break;
case -1:
default:
err = {'failed': true};
}
c.setErrors(err);
return err;
}
注意我把控件作为参数输入到"mapErr"函数中,通过"c.setErrors(err);"设置控件。
"return err;" 声明 return "ValidationErrors" 根据 "AsyncValidatorFn" 接口规范。
"gabriel.filter()"使用提取的用户名查询后端;和 returns 0、-100、-1 分别对应 "ok"、"duplicated" 和 "operation failed"
filter(json): Observable<{}>{
let body = JSON.stringify(json);
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({ headers: headers });
return this.http.post(Cons.filter, body, options).timeout(10000).map((res:Response) => res.json());
}
控件签入html文件
<form [formGroup]="sf" (ngSubmit)="signin()">
<ion-item>
<ion-label>UserName</ion-label>
<ion-input type="text" formControlName="userName" [class.invalid]="userName.dirty&&userName.invalid&&userName.errors!=null" ></ion-input>
</ion-item>
<p *ngIf="userName.dirty && userName.hasError('existed')">
Username already existed
</p>
<p *ngIf="userName.dirty && userName.hasError('failed')">
can not check validity of Username
</p>
我还发现,在一个表单控件中满足同步验证器之前,不会触发异步验证器。
在我的例子中,我还使用了内置的 Validators.pattern 来定义最小长度为 3。(参见上面的用户名 formControl 定义)
只要我的输入长度小于 3,自定义异步验证器就不会触发。