How do I get Invisible Recaptcha working with VueJS?

1,510 views
Skip to first unread message

Jean-Luc

unread,
Apr 4, 2017, 12:12:49 AM4/4/17
to reCAPTCHA
Hi. I am highly interested in using the Invisible Recaptcha (because it's invisible, to an extent) on my VueJS SPA.

VueJS, as far as I can find out, does not allow callback parameters so filling in `data-callback` with a callback name is not an option. It is also not an option to use a callback within the API URL. I have however managed to get a result.

Here is my code after removing all unnecessary code.

<template>
    <form class="login-form control">
        <div class="field is-grouped">
            <p class="control is-expanded"></p>
            <p class="control">
                <button class="button is-primary" ref="recaptcha" @click.prevent="validate">Register</button>
            </p>
        </div>
    </form>
</template>

<script>
    module.exports = {
        data() {
            return {
                hasRecaptchaRendered: false,
            }
        },

        methods: {
            onSubmit() {
                alert('submitted');
            },
            
            validate() {
                grecaptcha.render(this.$refs.recaptcha, {
                    'sitekey'  : window.Laravel.recapSite,
                    'callback' : this.onSubmit
                });

                if (this.hasRecaptchaRendered === false) {
                    grecaptcha.execute();

                    this.hasRecaptchaRendered = true;
                }
            }
        }
    }
</script>

When you click the register button, it will call `grecaptcha.render` and `grecaptcha.execute`. I played around with the code because although I can get it to work, it is not 100%.

When I click the submit button, it takes a few seconds for recaptcha to do it's thing and upon success, I do get my "submitted" alert. The second time I click the submit button, I can see in the network tab that everything was requested but nothing appears on the screen. The third, forth, fifth time and so on, it will work without that few second delay. I cannot figure out what is going on.

I did try and render the recaptcha once and calling execute multiple times but this didn't work. It only worked once and that was it. It appears as if I must re-render it multiple times and then execute.

What if I remove `grecaptcha.execute()` all together? The first click does request everything but nothing appears on the screen. Any subsequent clicks do work as expected.

I'm unsure if I'm able to call render any sooner. There is a `mounted` method which is triggered after the view has been rendered but it seems as if that occurs before the API has been successfully loaded as `grecaptcha` at that point doesn't exist. 

As I was writing this I came up with an idea of using a `setTimeout` before rendering the first time. I feel like this is dependent on how fast the API loads which could vary so I wouldn't call it a reliable solution but it does seem to work.

module.exports = {
    mounted() {
        setTimeout(this.render, 1000);
    },

    methods: {
        render() {
            grecaptcha.render(this.$refs.recaptcha, {
                'sitekey'  : window.Laravel.recapSite,
                'callback' : this.onSubmit
            });
        },

        onSubmit() {
            alert('submitted');

            this.render();
        }
    }
}

So what the above code does is 1 second after the component has mounted, it will render recaptcha, and then you will be able to click the button and it will do what recaptcha is supposed to do. Upon success, it will re-render otherwise it will not function again.

I'd like some input on what is the correct way to use invisible recaptcha with VueJS, if there even is one at this point in time. 

I'd also like to know that upon success, is recaptcha supposed to re-render? For whatever reason it doesn't function at all unless I do.

Thanks.
Reply all
Reply to author
Forward
0 new messages