AsyncValidator немного проще, чем ваш код. (на самом деле вы не можете использовать valueChanges observable).
Представьте, что у вас есть dataService с двумя функциями, которые возвращают наблюдаемое true, если существует, и false, если нет. Ну, я симулирую, используя оператор "of" rx js и задержку
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
}))
}
}
См. stackblitz
Примите во внимание:
- Я использую {updateOn: 'blur'} только для проверки, когда размытие
- Валидаторы возвращают наблюдаемое, в случае ошибки наблюдаемое из объект {ошибка: 'пока существует'}, в случае, если допустимая наблюдаемая ноль.
- Начиная с dataService вы получаете истину -если существует-или ложь-если нет - я использую (pipe (map) для преобразования ответа и использую 'of' rx js для возврата наблюдаемой
Если вы хотите использовать задержку, потому что вам не нравится {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">