In practical terms, how do I do an async grecapttcha call before submitting the form?
See all SO questions below, that address a less complex scenario.
Considerations:
Form must submit via both a submit button and via the Enter key (so no onClick handlers).
Prevent multiple form submissions.
Default implementation/use of grecaptcha fires on page ready and expires in a couple of minutes, making long forms fail if user takes their time filling them out. So delay running grecaptcha until the form is submitted.
Grecaptcha call is async, while form onSubmit requires an immediate response.
Grecaptcha is inaccessible in certain markets (I'm looking at you, China). Allow form submission if grecaptcha server is unavailable for any reason.
The following are similar questions on SO, that all fail to address all of the above:
javascript async await Submitting a form with onsubmit using Promise (relies on using a promise)
HTML form action and onsubmit issues (does not address the async requirement)
How to prevent form from being submitted? (this one relies on preventDefault, which is the opposite of what's needed - want to use the 'default' implementation only after an intercept)
Prevent form submission in the onsubmit event (another one advising to use preventDefault...)
Combining form onsubmit parameter with jquery submit event handler (this solution uses the clunky bind/unbind in addition to preventDefault - over-complicates things)
How to call google recaptcha code on submit button click (this one calls grecaptcha onLoad instead of onSubmit)
How to solve Google v3 reCaptcha timeout? Has a decent answer with fetching token once a minute on a timer
https://github.com/google/recaptcha/issues/302 As reported in the official repo
And because community likes to see some broken code, here's my version that works via the submit button but fails via the Enter key because it relies on onClick handler:
<script>
var onSubmit = function () {
$('#btn-submit').prop("disabled", true);
if (typeof grecaptcha == 'object') { //undefined behind the great firewall
grecaptcha.execute('@Config.ReCaptchaSiteKey', { action: 'login' }).then(function (token) {
window.document.getElementById('ReCaptchaToken').value = token;
$('form').submit();
});
} else {
window.document.getElementById('ReCaptchaToken').value = -1;
$('form').submit();
}
};
</script>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
@Html.HiddenFor(model => model.ReCaptchaToken)
@Html.EditorFor(model => model.Inventory)
<input type="button"
id="btn-submit"
value="Submit"
class="btn btn-default"
onclick="onSubmit()" />
}