Make "Ship to different address" mandatory if specific products are in WooCommerce cart

Viewed 506

I'm trying to add a snipped to activate the "Ship to other address" open by default, when a specific product is in the checkout.
I found Enable 'Ship to a different address' check box for specific products in Woocommerce related answer thread which is working perfectly!

However, it should not be possible to unselect the check box "Ship to other address". If a specific product is in the checkout, then providing a different shipping address is required.

Goal: Gray-out the "Ship to other address" checkbox for those specific products.

I just changed in the code $products_ids = array(10800, 11907); to feet my needs.

I already tried to unhook the function but then the whole code does not work. So I'm searching the best way to gray-out that checkbox but keep the code above fully working.

2 Answers

You could add a custom class to the checkout body tag when there are products in the cart.

So with a CSS rule you can hide the "Ship to a different address?" checkbox.

Using this answer:

You can take the code and create a new custom function (returns the same result as before, the function has not been modified except the product ids):

function check_if_product_is_in_cart() {

    $products_ids = array( 10800, 11907 );
    $found = $others_found = false;

    foreach ( WC()->cart->get_cart() as $cart_item ){
        if (in_array( $cart_item['data']->get_id(), $products_ids ) ){
            $found = true;
        } else {
            $others_found = true;
        }
    }

    if ( $found && ! $others_found ) {
        return true;
    } else {
        return false;
    }
        
}

Then you can enable or disable the checkbox based on the result of the function:

add_filter( 'woocommerce_ship_to_different_address_checked', 'filter_cart_needs_shipping_address');
function filter_cart_needs_shipping_address( $checked ) {
    return check_if_product_is_in_cart();
}

Finally you can use the same function to add the custom class to the checkout body tag:

add_filter( 'body_class', 'add_body_class' );
function add_body_class( $classes ) {
    if ( ! is_checkout() ) {
        return $classes;
    }
    if ( check_if_product_is_in_cart() ) {
        $classes[] = 'hide_ship_to_different_address_checkbox';
    }
    return $classes;
}

At this point you just have to add the CSS rules in the style sheet of your active theme:

The code has been tested and works. Add it to your active theme's functions.php.

If I have understood, you want to keep your code functionality, disabling the checkbox.

The best thing is to hide the checkbox first. Then to avoid the shipping address to be shown or hidden by clicking on the checkbox label, jQuery will remove it when it is checked.

The php code (and inline CSS):

// Hide the checkbox (inline CSS) - Only on checkout page
add_filter( 'wp_head', 'shipping_address_checkbox_ccs' );
function shipping_address_checkbox_ccs() {
    if( is_checkout() && ! is_wc_endpoint_url() ) {
        ?><style>body.checkout-hide-checkbox #ship-to-different-address-checkbox { display:none; } body.checkout-hide-checkbox #ship-to-different-address label { cursor: default; }</style><?php
    }
}

// Conditional function
function mandatory_shipping_address(){
    $products_ids = array(10800, 11907);
    $found = $others_found = false;

    foreach ( WC()->cart->get_cart() as $cart_item ){
        if ( in_array( $cart_item['data']->get_id(), $products_ids ) ){
            $found = true;
        } else {
            $others_found = true;
        }
    }
    return $found && ! $others_found ? true : false;
}

// Conditionally Enable checkbox (checked)
add_filter( 'woocommerce_ship_to_different_address_checked', 'filter_cart_needs_shipping_address');
function filter_cart_needs_shipping_address( $checked ) {
    return mandatory_shipping_address() ? true : $checked;
}

// Conditionally Add a body class - Only on checkout page
add_filter( 'body_class', 'shipping_address_checkbox_body_class' );
function shipping_address_checkbox_body_class( $classes ) {
    if( is_checkout() && ! is_wc_endpoint_url() && mandatory_shipping_address() ) {
        $classes[] = 'checkout-hide-checkbox';
    }
    return $classes;
}

The jQuery code:

// Remove the checkbox when is checked - Only on checkout page
add_action( 'template_redirect', 'cart_needs_shipping_address_js');
function cart_needs_shipping_address_js() {
    if( is_checkout() && ! is_wc_endpoint_url() ) :

    wc_enqueue_js( "jQuery( function($){
    var a = '#ship-to-different-address-checkbox';
    if( $(a).is(':checked') ) {
        $(a).remove(); // Remove checkbox
    } 
    });");
    endif;
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

So when checkbox is checked you will get (for your defined products):

enter image description here

Related