Does anybody have any idea how to handle such scenario? I want to display an notice message and disable place order button in the checkout page when non XX country has been selected and cart contains a particular product (not deliverable to foreign country).
I could do with the Jquery, but cannot access the Place order button as its form is being refreshed via AJAX everytime I change billing address. This is what I have come so far:
add_action( 'woocommerce_checkout_before_customer_details', 'display_shipping_notice' );
function display_shipping_notice() {
echo '<div class="shipping-notice woocommerce-error" role="alert" style="display:none">We cannot ship this product to your country. Please remove it from the cart to continue!</div>';
}
add_action( 'woocommerce_after_checkout_form', 'show_shipping_notice_js' );
function show_shipping_notice_js(){
?>
<script>
jQuery(function($){
var countryCode = 'LV', // Set the country code (That will display the message)
countryField = 'select#billing_country'; // The Field selector to target
function showHideShippingNotice( countryCode, countryField ){
if( $(countryField).val() !== countryCode && $('.shop_table tr').hasClass('id-27733')){
$('.shipping-notice').show();
$('.woocommerce-checkout-payment').hide();
}
else {
$('.shipping-notice').hide();
$('.woocommerce-checkout-payment').show();
}
}
// On Ready (after DOM is loaded)
showHideShippingNotice( countryCode, countryField );
// On billing country change (Live event)
$('form.checkout').on('change', countryField, function() {
showHideShippingNotice( countryCode, countryField );
});
});
</script>
<?php
}
function cart_item_class( $class, $values, $values_key ) {
if ( isset( $values[ 'product_id' ] ) ) {
$class .= ' id-' . $values[ 'product_id' ];
}
return $class;
}
add_filter( 'woocommerce_cart_item_class', 'cart_item_class', 10, 3 );
CodePudding user response:
There is no need to use jQuery or AJAX, also displaying a custom message via a HTML div is not necessary, as this can be done via wc_add_notice()
and WooCommerce hook(s).
In other words, take advantage of WooCommerce functionalities opposite to create it yourself.
If you want to perform this check only on the checkout page, you can use the woocommerce_order_button_html
hook:
function filter_woocommerce_order_button_text( $button ) {
// The targeted product ids
$targeted_ids = array( 30, 815 );
// Flag
$found = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
// True
if ( $found ) {
// Get billing country
$billing_country = WC()->customer->get_billing_country();
// Multiple country codes can be added, separated by a comma
$countries = array( 'BE', 'LV' );
// Checks if a value NOT exists in an array
if ( ! in_array( $billing_country, $countries ) ) {
$style = 'style="background:Silver !important; color:white !important; cursor: not-allowed !important; text-align:center;"';
$text = apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) );
$button = '<a class="button"' . $style . '>' . $text . '</a>';
// Clear all other notices
wc_clear_notices();
// Notice
wc_add_notice( __( 'We cannot ship this product to your country. Please remove it from the cart to continue!', 'woocommerce' ), 'error' );
}
}
return $button;
}
add_filter( 'woocommerce_order_button_html', 'filter_woocommerce_order_button_text', 10, 1 );
Or for a combination of the cart and checkout page you can use the woocommerce_check_cart_items
hook:
function action_woocommerce_check_cart_items() {
// The targeted product ids
$targeted_ids = array( 30, 815 );
// Flag
$found = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
// True
if ( $found ) {
// Get billing country
$billing_country = WC()->customer->get_billing_country();
// Multiple country codes can be added, separated by a comma
$countries = array( 'BE', 'LV' );
// Checks if a value NOT exists in an array
if ( ! in_array( $billing_country, $countries ) ) {
// Notice
wc_add_notice( __( 'We cannot ship this product to your country. Please remove it from the cart to continue!', 'woocommerce' ), 'error' );
// Remove proceed to checkout button
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
}
}
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );