[英]Validating formGroup which contains asyncValidator while in PENDING state
[英]Angular FormBuilder in Pending state when having more than one AsyncValidator
我正在嘗試向我的 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());
}
}
some-component.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,如果響應為真,則submitButtonEnabled
應返回真。
AsyncValidator 比您的代碼更容易一些。 (真的你不能使用 valueChanges 可觀察的)。
想象一下,你有一個帶有兩個函數的 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'} 我建議使用 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">
嘗試這個:
if (!control.valueChanges) {
return of(null as ValidationErrors);
}
if (!obs) {
obs = merge(
of(control.value),
control.valueChanges
).pipe(
debounceTime(500),
distinctUntilChanged(),
switchMap((login: string) => {
...
}),
map(_ => {
return id == null ?
null :
{ exists: true };
})
);
}
return obs.pipe(first());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.