Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: What is the usecase for emitting a null value if .reset() is callled and widget has a response ready #99

Open
1 of 4 tasks
eccentric93 opened this issue Apr 30, 2018 · 4 comments
Labels

Comments

@eccentric93
Copy link

Summary

I'm submitting a:

  • bug report
  • feature request
  • question / support request
  • other

Description

I am using invisible recaptcha in my angular component. I want to reset the form (along with re-captcha) if server validation fails, for that reason I call .reset() on the captcha ViewChild when I receive response from server

Issue is, a null value is emitted in this case
Although, this is in accordance with what doc says, I am unable to figure out what could be the usecase for this.

Thanks for your help

@DethAriel
Copy link
Owner

Hello, @eccentric93 ! This is a good question, actually, and there is a couple reasons for doing it this way:

  1. Keep the component state in sync with UI state. This one is straightforward - you don't want the checkbox to say "I'm checked" when it actually isn't
  2. Better timeout support. Suppose that reset() does not emit a null value. Then after a couple minutes this value will become invalid, but nothing will be able to tell the consumer that this happened. So, a user would submit an outdated reCAPTCHA value to the server, the server would fail validation, and return an error to the user.

Could you please elaborate on why this is an issue for you?

@eccentric93
Copy link
Author

Oh, thanks for the explanation. I think the confusion was caused for me as same EventEmitter was used to

  1. Tell whether captcha has been resolved
  2. Tell whether the captcha response which you already have(If you have) is invalid now as it might be reset / expired and you might want to stop sending the request to server

The second statement might be helpful only for devs using "Click to validate recaptcha" and not for the ones using "Invisible recaptcha"
(Reason being, when you click on the "I am not a Robot" button, the user might still take time to actually hit the submit button which sends request to server. But in "Invisible recaptcha" case, when user clicks the submit button, we already want to send the request to server without any delay, grecaptcha.execute() api is programatically called and its success handler is tied with actual form submit. So in this case I do not have an recaptcha response cached which might become invalid until the user hits submit)

@DethAriel
Copy link
Owner

So if i understood you correctly, the desired behavior in case of <re-captcha size="invisible"> is to not emit resolved(null) upon calling reset(), is that right?

@eccentric93
Copy link
Author

So if i understood you correctly, the desired behavior in case of is to not emit resolved(null) upon calling reset(), is that right?

IMHO, there should be no event emitted on reset(), as this is not an auto-generated event, this is called by user explicitly

grecaptcha.reset()

If user knows he needs to reset the re-captcha, why doesnt he do the other stuff too after calling .reset()?

There should be an event for expiration though, as this is auto-generated, not user controlled.

A different event emitter could be used for signalling both the usecases(onResolve and onExpire) for both "Click" and "Invisible" recaptcha options.

It is not that it is blocking anything, if users want to use invisible recaptcha, this is what they have to do now

<re-captcha #iRecaptcha siteKey="..." size="invisible" (resolved)="handleEmittedResponse($event)">

handleEmittedResponse(response){
    if(response === null) {
        // Response is null due to what? Expiration? reset?
        if(this.subscription){ // Cancel subscription
            this.subscription.unsubscribe();
        }
        return;
    }
    else{
        this.subscription = this.http.post(url).subscribe((data) => {
            if(data.error) { // Server validation failed
                // Print Error
                this.iRecaptcha.reset(); // This will un-necessarrily send null to handleEmittedResponse() now
            }
            else {
               // Rejoice! Print success
                this.iRecaptcha.reset(); // Enable user to re-send another request. Will send null in this case too
            }
        })
    }
}

This is what I think would help

<re-captcha #iRecaptcha siteKey="..." size="invisible" (resolved)="handleEmittedResponse($event)" (expired)="handleExpiration()">

handleEmittedResponse(response){
    this.subscription = this.http.post(url, response).subscribe((data) => {
        if(data.error) { // Server validation failed
            // Print error
            resetCaptcha();
        }
        else {
            // Rejoice ! Print success
            resetCaptcha();
        }
    })
}

handleExpiration(){
    if(this.subscription){ // Cancel subscription
        this.subscription.unsubscribe();
    }
}

resetCaptcha(){
    this.iRecaptcha.reset();
    // If user knows he needs to reset, let him do rest of the tasks here itself
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants