angular - 当具有多个 AsyncValidator 时,Angular FormBuilder 处于待处理状态
问题描述
我正在尝试在 Angular 中向我的表单添加一些自定义验证。问题是当我在表单中只有一个 AsyncValidator 时,一切都按预期工作,所以我更改了一个值并且表单状态更改为Valid
. 当我有两个 AsyncValidator 时,表单会保持Pending
状态,直到我更改它们。
这是我的代码:
uniqueValue.validator.ts
export function UniqueValidator(service: ExistsService, originalValue: string = null): AsyncValidatorFn {
return control => {
if (control.valueChanges == null) {
return of(null);
}
return control.valueChanges
.pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap(value => {
if (value === originalValue) {
control.markAsPristine();
return of(false);
}
return service.exists(value);
}),
map((unique: boolean) => (!unique ? null : { 'notUnique': true })),
first());
}
}
一些组件.component.ts
ngOnInit() {
this.form= this.fb.group({
email: [this.email,
[Validators.required],
UniqueValidator(this.myService)
],
username: [this.userName,
[Validators.required],
UniqueValidator(this.myService)
],
fullName: [this.fullName]
});
this.form.markAsPristine();
}
submitButtonEnabled(): boolean {
return this.form.valid
&& this.form.dirty;
}
ps 这是一个Edit Form
,因此所有字段的初始状态中总会有值。因此,当表单首次加载时,两个字段(电子邮件和用户名)都是有效的,并且其中一个更改将触发 AsyncValidator,如果响应为 true,submitButtonEnabled
则应返回 true。
解决方案
AsyncValidator 比您的代码更容易一些。(真的你不能使用 valueChanges observable)。
想象一下,你有一个 dataService 有两个函数,如果存在则返回一个可观察的 true,如果不存在则返回 false。好吧,我通过使用“of”rxjs 运算符和延迟来模拟
export class DataService {
constructor() { }
emails=['qqq@qqq.com','aaa@aaa.com']
userNames=['qqq','aaa','bbb']
existEmail(email:string)
{
return of(this.emails.indexOf(email)>=0?true:false).pipe(delay (1000))
}
existUser(userName:string)
{
return of(this.userNames.indexOf(userName)>=0?true:false).pipe(delay (1000))
}
}
您可以创建一个像
form=new FormGroup( {
name:new FormControl('',{asyncValidators:this.uniqueName(),updateOn:'blur'}),
email:new FormControl('',{asyncValidators:this.uniqueEmail(),updateOn:'blur'}),
})
uniqueName()
{
return (control:FormControl)=>{
return this.dataService.existUser(control.value).pipe(map(x=>
{
return x?{error:'yet exist'}:null
}))
}
}
uniqueEmail()
{
return (control:FormControl)=>{
return this.dataService.existEmail(control.value).pipe(map(x=>
{
return x?{error:'yet exist'}:null
}))
}
}
查看堆栈闪电战
考虑到:
- 我使用 {updateOn:'blur'} 只检查何时模糊
- 验证器返回一个 Observable,如果错误,则返回对象 {error:'yet exists'} 的可观察对象,如果有效,则返回 null 的可观察对象。
- 从 dataService 你收到真 - 如果存在 - 或假 - 如果不 - 我使用 (pipe(map) 来转换响应,并使用 'of' rxjs 返回可观察的
如果你想使用延迟,因为你不喜欢 {updateOn:'blur'} 我建议使用 tro auxiliars formControls
control1=new FormControl()
control2=new formControl()
form=new FormGroup( {
name:new FormControl('',{asyncValidators:this.uniqueName()}),
email:new FormControl('',{asyncValidators:this.uniqueEmail()}),
})
this.control1.valueChanges.pipe(
debounceTime(400),
distinctUntilChanged()).subscribe(res=>{
this.form.get('name').setValue(res)
})
this.control2.valueChanges.pipe(
debounceTime(400),
distinctUntilChanged()).subscribe(res=>{
this.form.get('email').setValue(res)
})
你不使用表格,你使用
<input [formControl]="control1">
<input [formControl]="control2">
推荐阅读
- unity3d - unity GUID 在不同计算机上是否唯一?
- node.js - 无法使用 Knex.js 迁移验证用户:Node 中的最新版本
- python - argparse — 查明是否提供了参数或使用了默认值
- java - Omnet++ 中的模拟时间
- airflow - Google Cloud Composer (Apache Airflow) 无法访问日志文件
- javascript - 如何在去抖动中传递参数
- python - 如何使用GDAL python加快从栅格文件中提取数据的速度
- mongodb - 尝试将多个 CSV 文件导入 MongoDB
- css - 从 svg 中删除视图框/容器
- django - 在 django 中过滤相关名称字段