skip to Main Content

I’ve been looking for a solution to this for a while now… I am trying to show or hide specific shipping rates based on a radio button option added to the Woocommerce checkout page. But I don’t know anything about Ajax & JQuery which I believe it requires.

Basically if a user selects radio option_1 it will ONLY show ‘flat_rate:1‘ & ‘flat_rate:2‘. If the user selects radio option_2 it will ONLY show ‘flat_rate:3‘ & ‘flat_rate:4

Click here for example of checkout screen

Here is the code for my radio buttons displayed on checkout page:

add_action( 'woocommerce_review_order_before_payment','tc_checkout_radio_choice' );
function tc_checkout_radio_choice() {
$businesstype = array(
   'type' => 'radio',
   'class' => array( 'business_residential' ),
   'required' => true,
   'options' => array(
       'option_1' => 'Business',
       'option_2' => 'Residential',
),
);
   echo '<div id="checkout-radio">';
   echo '<h3>Select Your Business Type</h3>';
   woocommerce_form_field( 'radio_choice', $businesstype );
   echo '</div>';
}

The closest example I’ve seen comes from an answer provided by ‘LoicTheAztec‘ in this post here: Show/hide shipping methods based on a WooCommerce checkout field value

I’m completely lost with this and the more I try to solve it, the more I get confused.

2

Answers


  1. Chosen as BEST ANSWER

    If anyone wants to know how to make this a required option with an error notification before payment, this is what I did...

    To de-select the radio buttons I removed the value from:

    //if( empty($field_value) )
        $field_value = '';
    

    And added this code to the checkout process at the end of the code from Loic, which adds a notification message if a radio button has not been selected:

    // Show notice if customer does not select a business type 
    add_action( 'woocommerce_checkout_process', 'business_type_error_message' );
    function business_type_error_message() {
    if ( ! (int) isset( $_POST['customer_type'] ) ) {
        wc_add_notice( __( 'Please select an order type to calculate the correct shipping and proceed with your order.' ), 'error' );
    }
    }
    

    Hope this helps others out there!


  2. 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:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search