1

I'm trying to make a custom AsyncValidatorFn that will send a post request to the node.js/express server only after the user has finished typing in his email/username to check if it is unique, kinda like how Validators.required only pops up the error after you've clicked the input field, and then clicked out, without typing anything in.

I used this guide to help me start out and this is what I have for now:

  • In the form group in the component:

    
        email: ["", 
                    [Validators.required, Validators.email],
                    EmailUniqueValidator.createValidator(this.usersService)
                  ]
    
    
  • The validator class itself:

    
        export class EmailUniqueValidator{
            static createValidator(usersService:UsersService):AsyncValidatorFn{
                return(control: AbstractControl): Observable<ValidationErrors> =>{
                    return usersService.checkEmail(control.value).pipe(
                        map((result:boolean) => result ? null: {emailUsed:true})
                    )
                }
            }
        }
    
    
  • The users service function:

    
        checkEmail(email:string){
            const data={
              email:email
            }
            const url = `${this.baseUrl}${ApiPaths.User}/checkEmail`
            return this.http.post(url,data).pipe(
              map((result)=>result["message"]=="email ok"?true:false)
            )
          }
    
    
  • And the backend function for the emailCheck

    
        emailCheck = (req:Request, res:Response)=>{
                let emailLog = req.body.email;
                console.log("email check: "+ emailLog)
                User.findOne({email:req.body.email}, (err,result)=>{
                    if(err) console.log(err)
                    if(result){
                        res.json({message:"duplicate email"})
                        console.log("duplicate email")
                    }
                    else{
                        res.json({message:"email ok"})
                        console.log("email ok")
                    }
                })
            }
    
    

I have seen How to delay the .keyup() handler until the user stops typing? and I think it should be helpful, but I can't figure out how to translate it into something that can work in my code.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
kljaja998
  • 13
  • 3
  • Yow bro, why don’t you use onBlur, onBlur event listener fires when the input looses focus, so when the users types the username and then they move to another field, that event will fired – Ernesto Jun 25 '21 at 23:01
  • Where can I use the onBlur? – kljaja998 Jun 25 '21 at 23:05
  • I guess you is using angular. here is the answer https://stackoverflow.com/questions/34918198/how-to-use-onblur-event-on-angular2/46585098 – Ernesto Jun 26 '21 at 00:06
  • Yes, but I would like to use it with my Validator, not fudge it with some side-function. – kljaja998 Jun 26 '21 at 00:11
  • you can configure the form control to validate on blur when you define the form control itself. email: ['', {updateOn: 'blur', validators:[....], asyncValidators: [...]}] – the_makeshift_dev Jun 26 '21 at 00:54
  • That is most likely what I am looking for, is there any way to do it for specific validators or do you have to do it for all of them? – kljaja998 Jun 26 '21 at 01:06
  • this will configure it for all the validators on the formControl. AFAIK there is no way to apply this to specific validators.. Maybe an alternative approach would be to pattern match the form value to your email template in your async validator before dispatching the post call?? – the_makeshift_dev Jun 26 '21 at 01:10
  • Well, that wouldn't work, since the emails already pass the Validators.email, because asyncValidators are already called only after all of the validators pass, but I'm going to say that the {updateOn:'blur'} is the thing I'm looking for, no use in overcomplicating it. Do you want to post the answer so I can mark it as "answered"? – kljaja998 Jun 26 '21 at 01:19

1 Answers1

1

you can configure the form control to validate on blur when you define the form control itself.

email: ['', {updateOn: 'blur', validators:[...], asyncValidators: [...]}]