30

I want to reset Google reCaptcha widget when I submit my form via AJAX and have some input errors or form is sent. I'm using multiple widgets on the same page so I render these widgets explicitly.

My HTML code:

<div class="g-recaptcha" id="recaptcha-1"></div>
<div class="g-recaptcha" id="recaptcha-2"></div>
...
<div class="g-recaptcha" id="recaptcha-20"></div>

Loading widget

<script src="https://www.google.com/recaptcha/api.js?onload=reCaptchaCallback&render=explicit&hl=en" async defer></script>
<script>
    var reCaptchaCallback = function() {
        var elements = document.getElementsByClassName('g-recaptcha');
        for (var i = 0; i < elements.length; i++) {
            var id = elements[i].getAttribute('id');
            grecaptcha.render(id, {
                'sitekey' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
            });
        }
    };
</script>

After submit form:

var id = $('.g-recaptcha', form).attr('id');
grecaptcha.reset(id);

Form is the instance of the submitted form.

Everything works fine when form is fill correctly. But reCaptcha doesn't reset or reload. It try this grecaptcha.reset() but no results.

Any idea?

quarky
  • 710
  • 2
  • 13
  • 36

6 Answers6

47

The grecaptcha.reset() method accepts an optional widget_id parameter, and defaults to the first widget created if unspecified. A widget_id is returned from the grecaptcha.render() method for each widget created. So you need to store this id, and use it to reset that specific widget:

var widgetId = grecaptcha.render(container);
grecaptcha.reset(widgetId);

See here.

levi
  • 23,693
  • 18
  • 59
  • 73
  • Many thanks, I hope that this will works but not. I must doing something wrong. I have update my code. Maybe it helps. I'm now getting error: `Invalid ReCAPTCHA client id: recaptcha-1`. Don't understand why the ID is wrong. – quarky May 04 '15 at 21:02
  • 1
    @quarky you need to store the value returned by `grecaptcha.render`, and perhaps attach it to the element. eg: `var id = grecaptcha.render(etc); elements[i].setAttribute('cid', id);` and then use that id for removal. – levi May 04 '15 at 21:50
  • thank you very much. Yes that was the problem. Now it is working fine. Many thanks. – quarky May 04 '15 at 23:00
  • 4
    Just in case anyone is going to be checking the ID, it is a zero-based index. Therefore, ``(!widgetId)`` can be false if the widget exists. – SameOldNick Jul 18 '15 at 23:07
  • 1
    grecaptcha.render(container); always return 0 as id, what wrong? – Oleg Abrazhaev Aug 21 '15 at 10:29
  • 3
    To answer Oleg, it's a zero-based index, so the first recaptcha widget will always return 0 as the ID. It's working properly. – Sean Kendle Mar 27 '17 at 18:38
1

You are passing the wrong id.

$('.g-recaptcha', form).attr('id');

Your selector will capture all 20 reCaptcha widget, but only return a single DOM id (the first reCaptcha). So your code is actually resetting the first recaptcha.

Jason
  • 848
  • 6
  • 17
0

Just edited your code to create a dynamic widget.

<script>
    var reCaptchaCallback = function() {
        var elements = document.getElementsByClassName('g-recaptcha');
        for (var i = 0; i < elements.length; i++) {                
            widgetId+i = grecaptcha.render('recaptcha-'+i, {
                'sitekey' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
            });
        }
    };
</script>

And after you have successfully completed the above task, change in the AJAX success: response

grecaptcha.reset(widgetId+id);

Here the id would be the same that is generated from the below for Loop.

Viral Patel
  • 485
  • 1
  • 5
  • 11
0

I have two google captcha in same page, two different form

<form id="form1">    
<input type="text" name="form1-input">
<div class="g-recaptcha" data-sitekey="XXXXXXXXXXXXXXXXX"></div>
</form>

and

<form id="form2">    
<input type="text" name="form2-input">
<div class="g-recaptcha" data-sitekey="XXXXXXXXXXXXXXXXX"></div>
</form>

You can reset first captcha by

 grecaptcha.reset(); or grecaptcha.reset(0);

And Second Captcha by index (1)

grecaptcha.reset(1);
YasirPoongadan
  • 683
  • 6
  • 19
0

I had an issue where there were multiple recaptchas on the page, some were hidden. In this case I had to loop through all of them and reset them like this:

                var count = 0;
                $(".g-recaptcha").each(function () {
                    grecaptcha.reset(count);
                    count++;
                });
0

As noted by other answers here, reset() method defaults to the first widget when there are multiple on the same page, and the API doesn't offer a simple or reliable way to find the widget Id in code. A solution to this is to load widgets explicitly and store the widget Id in a data attribute

<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaLoaded&render=explicit"></script>

<script>
    function recaptchaLoaded() {
    
        document.querySelectorAll('.g-recaptcha').forEach((el, i) => {
            var widgetId = grecaptcha.render(el);
            el.setAttribute('data-grecaptcha-id', widgetId);
        });
    
    }

    document.getElementById("mybutton").addEventListener("click", (event) => {
        var widgetId = document.getElementById("mycaptcha").getAttribute('data-grecaptcha-id');
        grecaptcha.reset(widgetId);
    });

</script>

Note that the script URL must include render=explicit and the name of your onload callback method

Phil
  • 951
  • 12
  • 16