I integrated the new hidden reCAPTCHA (v2) framework which by default verifies the user with the click
event of the submit button. But this event is triggered before the built-in HTML5 form validation. I am looking for a way to make it in the expected order: form validation first, reCAPTCHA after.
问题:
回答1:
You have to do it programmatically thanks to a new v2 grecaptcha
method: grecaptcha.execute()
so that recaptcha doesn't replace the button's default click event which was preventing the default HTML5 form validation.
The event path is:
- Submit button click event: browser built-in form validation
- Form submit event: call
grecaptcha.execute()
- reCAPTCHA callback: submit the form
$('#form-contact').submit(function (event) {
event.preventDefault();
grecaptcha.reset();
grecaptcha.execute();
});
function formSubmit(response) {
// submit the form which now includes a g-recaptcha-response input
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js"></script>
<form action="?">
<div class="g-recaptcha"
data-sitekey="your-key"
data-size="invisible"
data-callback="formSubmit">
</div>
<button type="submit">Submit</button>
</form>
回答2:
Here is my solution to get HTML5 validation + Invisible recaptcha:
HTML:
<form id="my-form">
<!-- Your form fields ... -->
<div class="g-recaptcha"
data-sitekey="..."
data-callback="submitMyForm"
data-size="invisible">
</div>
<button type="submit">Submit</button>
</form>
JS:
var myForm = $('my-form');
function submitMyForm () {
myForm.trigger('submit', [true]);
}
$(function () {
myForm.on('submit', function (e, skipRecaptcha) {
if(skipRecaptcha) {
return;
}
e.preventDefault();
grecaptcha.execute();
});
})
回答3:
Hi got a working solution here. Working with invisible Recaptcha.
jQuery(document).ready(function() {
var commentform = jQuery("#commentform");
commentform.on("click", "#submit-comment", function(e) {
if(commentform[0].checkValidity()) {
e.preventDefault();
grecaptcha.execute();
}
});
});
function submitCommentForm(data) {
document.getElementById("commentform").submit();
}
<form action="blaba.php" method="post" id="commentform" class="comment-form">
<div class="form-submit">
<div data-callback="submitCommentForm" data-sitekey="yourkey" class="g-recaptcha" data-size="invisible">
<button id="submit-comment">Leave a comment</button>
</div>
</form>
回答4:
I was wanting the same behavior, but using the new recaptcha, the invisible one. After looking at some code and testing some stuff, I got into this. The main difference is that this uses the default browser validation as well:
var contact_form;
$(function() {
contact_form = $('#contact-form');
contact_form.submit(function (event) {
if ( ! contact_form.data('passed')) {
event.preventDefault();
grecaptcha.execute();
}
});
});
function sendContactForm(token) {
contact_form.data('passed', true);
contact_form.submit();
}
It basically stores the jquery form object in a global var, including, it uses sendContactForm
as the callback, but when called by the recaptcha, it sets a data var named passed
, which allows the form to not be prevented. It's exactly the same behavior as recaptcha would normally do, but with that condition.
Update: re-looking at my code right reminds me that it probably needs a way to restore data passed to false
after grecaptcha's execution. Consider that if you'll implement this.
回答5:
I had this problem as the default method seems to override the html5 form validation. I also wanted all code to be generic rather than hard coding any functions/element names. In the end I came up with the following code using the v3 api -
HTML
<form method="post" action="?" class="ui-recaptcha" name="my_form_name">
...
<input type="submit" value="Submit">
</form>
<script src="//www.google.com/recaptcha/api.js?render={key}" async defer></script>
Javascript (I'm using jQuery but would be fairly easy to adapt to vanilla js)
$('.ui-recaptcha').submit(e => {
var form = e.target;
if( $(form).data('recaptcha-done') )
return;
e.preventDefault();
grecaptcha.execute('{key}', {'action': $(form).attr('name')}).then(token => {
$(form).append($('<input>').attr({'type': 'hidden', 'name': 'g-recaptcha-response', 'value': token}));
$(form).data('recaptcha-done', true);
$(form).submit();
});
});
I found that just calling submit
as in some examples above caused a loop for me, which would make sense seeing as the recaptcha handler runs on the submit
event.
This runs recaptcha for any ui-recaptcha
form, passes the form name
attribute as the action which can be seen in reCaptcha console, and then inserts the token into the form. Once run it sets a data attribute on the form so the recursive call to submit doesn't try to run recaptcha again.
回答6:
let siteKey = "...";
$("form").submit(function (eventObj) {
var myForm = this;
eventObj.preventDefault();
grecaptcha.execute( siteKey, {
action: "submit"
})
.then(function (token) {
$('<input />').attr('type', 'hidden')
.attr('name', "g_recaptcha_response")
.attr('value', token)
.appendTo(myForm);
myForm.submit();
});
});
This will execute recapcha, wait for response, add hidden attribute g_recaptcha_response to any form when browser try to submit it and then actually submit it. You need global variable siteKey