问题
I am trying to create a step in checkout to confirm your order. I'm thinking when the place order button is clicked AND the checkout fields are valid I could run some JS to show a modal or whatever.
Is there a JS trigger/event similar to checkout_place_order that runs after validation? For example, I can use the following but it happens before validation. Maybe there is a way to trigger validation from inside there and display my modal based off that?
var checkout_form = $('form.checkout');
checkout_form.on('checkout_place_order', function () {
// do your custom stuff
return true; // continue to validation and place order
return false; // doesn't validate or place order
});
There is also the woocommerce_after_checkout_validation hook but I am not sure how to utilize it to achieve what I'm after.
I am open to ideas...
回答1:
I was able to figure this out finally, Its more of a workaround since I don't think there is a clear way to do this.
As soon as the "Place Order" button is clicked, we use the checkout_place_order event to place a hidden field with a value set to 1.
var checkout_form = $('form.checkout');
checkout_form.on('checkout_place_order', function () {
if ($('#confirm-order-flag').length == 0) {
checkout_form.append('<input type="hidden" id="confirm-order-flag" name="confirm-order-flag" value="1">');
}
return true;
});
Next, we use the hook woocommerce_after_checkout_validation to check our hidden input and if the value is 1 add in error (This stops the order from going through).
function add_fake_error($posted) {
if ($_POST['confirm-order-flag'] == "1") {
wc_add_notice( __( "custom_notice", 'fake_error' ), 'error');
}
}
add_action('woocommerce_after_checkout_validation', 'add_fake_error');
Last, we use the checkout_error event to determine if there was a real validation or if if there is only 1 error, the error we added. If there is only 1 error it means validation passed so we can show our modal (or whatever you need to do).
$(document.body).on('checkout_error', function () {
var error_count = $('.woocommerce-error li').length;
if (error_count == 1) { // Validation Passed (Just the Fake Error I Created Exists)
// Show Confirmation Modal or Whatever
}else{ // Validation Failed (Real Errors Exists, Remove the Fake One)
$('.woocommerce-error li').each(function(){
var error_text = $(this).text();
if (error_text == 'custom_notice'){
$(this).css('display', 'none');
}
});
}
});
Inside my modal I have a confirm button that sets our hidden field value to nothing and clicks the place order button again. This time the order will go through because we are checking for the hidden input value of 1.
$('#confirm-order-button').click(function () {
$('#confirm-order-flag').val('');
$('#place_order').trigger('click');
});
回答2:
As far as I know, there is no hooks in between validation and order creation process, that will allow you to interact with customer, making some actions.
Using jQuery and Sweet Alert component (SWAL 2), here is an example of code that will disable the "Place Order" button displaying a Sweet Alert with confirmation buttons. It's not perfect, but it answers partially your question.
Once customer will confirm, the "Place Order" button will be enabled back and it will be triggered by the code… If the customer use the cancel button, Checkout review order will be refreshed (Ajax).
The code:
add_action( 'wp_footer', 'checkout_place_order_script' );
function checkout_place_order_script() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
// jQuery code start below
?>
<script src="https://unpkg.com/sweetalert2@8.8.1/dist/sweetalert2.all.min.js"></script>
<script src="https://unpkg.com/promise-polyfill@8.1.0/dist/polyfill.min.js"></script>
jQuery( function($){
var fc = 'form.checkout',
pl = 'button[type="submit"][name="woocommerce_checkout_place_order"]';
$(fc).on( 'click', pl, function(e){
e.preventDefault(); // Disable "Place Order" button
// Sweet alert 2
swal({
title: 'Are you sure?',
text: "You are about proceed the order",
type: 'success',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: "Yes let's go!"
}).then((result) => {
if (result.value) {
$(fc).off(); // Enable back "Place Order button
$(pl).trigger('click'); // Trigger submit
} else {
$('body').trigger('update_checkout'); // Refresh "Checkout review"
}
});
});
});
</script>
<?php
endif;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
回答3:
I got a fast and simple JS decision for myself in this case (there were woocommerce and stripe forms). That is based on preventing the checkout button from submit but still makes forms verifications.
// making the wrap click event on dinamic element
$('body').on('click', 'button#place_order_wrap', function(event) {
// main interval where all things will be
var validatoins = setInterval(function(){ happen
// checking for errors
if(no_errors==0){
// making the setTimeout() function with limited time like 200ms
// to limit checkout function for just make verification
setTimeout(function(){
// triggering original button
$('button#place_order').click();
// if there some errors, stop the interval, return false
if(($('element').find('ul.woocommerce_error').length!==0)||($('element').find('.woocommerce-invalid-required-field').length!==0)){
clearInterval(validatoins);
return false;
}else{
no_errors=1;
}
}, 200);
}
if(no_errors==1){
// same error checking
if($('#step5').find('ul.woocommerce_error').length!=0||($('#step5').find('.woocommerce-invalid-required-field').length!==0)){
// if there some errors, stop the interval, return false
clearInterval(validatoins);
return false;
}
setTimeout(function(){
// if no errors
if(($('#step5').find('ul.woocommerce_error').length==0)&&($('#step5').find('.woocommerce-invalid-required-field').length==0)){
// do something, mark that finished
return false;
}
}, 1000);
// if something finished
if() {
setTimeout(function(){
// trigger original checkout click
$('button#place_order').click();
clearInterval(validatoins);
}, 1000);
}
}
}, 1000);
}
来源:https://stackoverflow.com/questions/52726635/hooking-after-validation-but-before-order-create-in-woocommerce-checkout