Here is the correct way to show hide shipping methods based on multiple radio buttons choice on checkout page, that requires to use PHP, Ajax, jQuery and WC Session.
When "Business" radio button is selected (default choice), flat_rate:3
and flat_rate:4
shipping methods will be hidden, so customer will only be able to choose flat_rate:1
or flat_rate:2
shipping methods.
If "Residential" radio button is selected then flat_rate:1
and flat_rate:2
shipping methods will be hidden, so customer will only be able to choose flat_rate:3
or flat_rate:4
shipping methods.
The code:
// Display a Custom radio buttons fields for shipping options
add_action( 'woocommerce_review_order_before_payment','checkout_customer_type_radio_buttons' );
function checkout_customer_type_radio_buttons() {
$field_id = 'customer_type';
echo '<div id="customer-type-radio">';
echo '<h3>' . __("Select Your Business Type", "woocommerce") . '</h3>';
// Get the selected radio button value (if selected)
$field_value = WC()->session->get( $field_id );
// Get customer selected value on last past order
if( empty($field_value) )
$field_value = WC()->checkout->get_value( $field_id );
// The default value fallback
if( empty($field_value) )
$field_value = 'Business';
woocommerce_form_field( $field_id, array(
'type' => 'radio',
'class' => array( $field_id ),
'required' => true,
'options' => array(
'Business' => __('Business', 'woocommerce'),
'Residential' => __('Residential', 'woocommerce'),
),
), $field_value );
echo '</div>';
}
// Conditionally show/hide shipping methods
add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 );
function shipping_package_rates_filter_callback( $rates, $package ) {
$customer_type = WC()->session->get( 'customer_type' ); // Get the customere type
if ( $customer_type === 'Business' ) {
if( isset( $rates['flat_rate:3'] ) )
unset( $rates['flat_rate:3'] );
if( isset( $rates['flat_rate:4'] ) )
unset( $rates['flat_rate:4'] );
}
elseif ( $customer_type === 'Residential' ) {
if( isset( $rates['flat_rate:1'] ) )
unset( $rates['flat_rate:1'] );
if( isset( $rates['flat_rate:2'] ) )
unset( $rates['flat_rate:2'] );
}
return $rates;
}
// function that gets the Ajax data
add_action( 'wp_ajax_get_customer_type', 'wc_get_customer_type' );
add_action( 'wp_ajax_nopriv_get_customer_type', 'wc_get_customer_type' );
function wc_get_customer_type() {
$field_id = 'customer_type';
if ( isset($_POST[$field_id]) && ! empty($_POST[$field_id]) ){
WC()->session->set($field_id, $_POST[$field_id] );
}
echo json_encode( WC()->session->get( $field_id ) );
die(); // (required)
}
// The Jquery Ajax script
add_action( 'wp_footer', 'custom_checkout_ajax_jquery_script' );
function custom_checkout_ajax_jquery_script() {
$field_id = 'customer_type';
if( WC()->session->__isset($field_id) )
WC()->session->__unset($field_id);
// Only on checkout when billing company is not defined
if( is_checkout() && ! is_wc_endpoint_url() ):
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
var fieldId = 'p#customer_type_field input';
function userTypeTriggerAjax( customerType ){
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'get_customer_type',
'customer_type': customerType,
},
success: function (result) {
// Trigger refresh checkout
$('body').trigger('update_checkout');
console.log(result);
}
});
}
// On start
if( $(fieldId).val() != '' ) {
userTypeTriggerAjax( $(fieldId).val() );
}
// On change
$(fieldId).change( function () {
userTypeTriggerAjax( $(this).val() );
});
});
</script>
<?php
endif;
}
// Enabling, disabling and refreshing session shipping methods data
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
$bool = true;
if ( in_array( WC()->session->get('customer_type' ), ['Business', 'Residential'] ) )
$bool = false;
// Mandatory to make it work with shipping methods
foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
}
WC()->cart->calculate_shipping();
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Code based on this related threads: