How can I trigger the rendering of a recaptcha
after a Vue.js
component has mounted? It functions correctly on initial load and reload, but throws an error when navigating away to a different url
and using the browser back button.
Here is how it's set up:
The
api
script is loaded at the bottom of the page like this:<script src='https://www.google.com/recaptcha/api.js' async></script>
On that page, a globally registered component named
Contact.vue
is rendered which contains a local component calledRecaptcha.vue
:<app-recaptcha @recaptchaResponse="updateRecaptchaResponse"></app-recaptcha>
The code for Recaptcha.vue
looks like this:
<template>
<div id="app-recaptcha">
<div :id="placeholderId"></div>
</div>
</template>
<script>
export default {
data() {
return {
sitekey: 'key_here',
placeholderId: 'grecaptcha',
widgetId: null
}
},
mounted() {
this.$nextTick(function () {
this.render();
});
},
methods: {
render() {
this.widgetId = window.grecaptcha.render(this.placeholderId, {
sitekey: this.sitekey,
callback: (response) => {
this.$emit('recaptchaResponse', response);
}
});
},
reset() {
window.grecaptcha.reset(this.widgetId);
}
}
}
</script>
<style>...</style>
During normal page load or reload, this.render()
runs without issues. However, upon returning via the browser back button from another url
, an error is triggered:
Error in nextTick: "TypeError: window.grecaptcha.render is not a function"
.
I attempted to:
set a variable on the
onload
event of theapi
script:<script src='...' onload="window.script = { recaptcha: 'ready' }" async></script>
then add it as a property in
data()
ofRecaptcha.vue
:ready: window.script.recaptcha
next, I added a watcher on the
ready
property and within that watcher I tried to runthis.render()
Unfortunately, I was unsuccessful in resolving the error. It seems that even during normal load/reload situations, the api
script may be loading after the component mounts, rendering this.render()
in the mounted()
hook ineffective.
Do you have any suggestions on how I can notify Recaptcha.vue
when the external script has finished loading, ensuring the recaptcha
is rendered only then?