Cannot render reCaptcha module more than once on my Polymer app: Uncaught Error: reCAPTCHA has already been rendered in this element

Total
12
Shares

Having trouble with a reCaptcha module in a Polymer 1 app.

I can use this module once (on the register form) but if I try to use it on any other component results in an error: Uncaught Error: reCAPTCHA has already been rendered in this element.

  • Initially thought the problem was because I loaded the recaptcha script inside the module so I moved that to index.html. But the problem continues to persist.

  • Tried using grecaptcha.reset() in various places to unload the widget so it can be rendered in other components.

Inside recaptcha-module-html:

<dom-module id="recaptcha-module">
    <template>
        <div class="captcha-container">
            <div id="captcha"></div>
        </div>
    </template>
    <script>
        Polymer({
            is: "recaptcha-module",
            ready: function () {
                this.recaptchaCallback = this.recaptchaCallback.bind(this)
                this.recaptchaExpired = this.recaptchaExpired.bind(this)
                window.recaptchaCallback = this.recaptchaCallback
                window.recaptchaExpired = this.recaptchaExpired
            },

            attached: function () {
                grecaptcha.render('captcha', {
                    'sitekey': {SITE_KEY_HERE}
                    'size': 'compact',
                    'callback': 'recaptchaCallback',
                    'expired-callback': 'recaptchaExpired'
                });
            },

            recaptchaCallback: function () {
                this.fire('recaptcha-success')
            },

            recaptchaExpired: function () {
                this.fire('recaptcha-expired')
            }

        });
    </script>
</dom-module>

Loading the recaptcha script in index.html:

  <script src="https://www.google.com/recaptcha/api.js">
  </script>

How I try to load the recaptcha-module in other components:

<link rel="import" href="recaptcha-module.html">
...
<recaptcha-module></recaptcha-module>

I expect that the module can be imported and used in multiple form components with but doing so causes an error and the widget refuses to be loaded more than once.


Solution

This issue was caused because the module did not assign a unique ID to the placeholder reCaptcha element. In order to fix the issue I created a property called elementid that could be used to give each render of the reCaptcha element a unique ID.

<dom-module id="recaptcha-module">
    <template>
        <div class="captcha-container">
            <div class="captcha" id="[[elementid]]"></div>
        </div>
    </template>
    <script>
        Polymer({
            is: "recaptcha-module",
            properties: {
                elementid : String,
                captchastyle : String
            },
            ready: function () {
                this.recaptchaCallback = this.recaptchaCallback.bind(this)
                this.recaptchaExpired = this.recaptchaExpired.bind(this)
                window.recaptchaCallback = this.recaptchaCallback
                window.recaptchaExpired = this.recaptchaExpired
            },

            attached: function () {
                grecaptcha.render(this.elementid, {
                    'sitekey': {MY_SITE_KEY},
                    'size': this.captchastyle,
                    'callback': 'recaptchaCallback',
                    'expired-callback': 'recaptchaExpired'
                });
            },

            recaptchaCallback: function () {
                this.fire('recaptcha-success')
            },

            recaptchaExpired: function () {
                this.fire('recaptcha-expired')
            }

        });
    </script>
</dom-module>

Then you can import the module and use the custom element anywhere else by giving it a unique ID. Like so:

<recaptcha-module elementid="UNIQUE_ID" captchastyle="normal"></recaptcha-module>
Leave a Reply

Your email address will not be published. Required fields are marked *