Show or hide checkout fields based on shipping method in Woocommerce 3

I’m trying to hide checkout fields based on shipping method.

function premove_billing_checkout_fields($fields) {
    global $woocommerce;
    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_shipping = $chosen_methods[0];

    if( $chosen_shipping === 'local_pickup:20' ) {
       unset($fields['billing']['billing_postcode']);
       unset($fields['billing']['billing_state']);
       unset($fields['billing']['billing_country']);
    }

    if( $chosen_shipping === 'wc_custom_shipping_pickpoint' ) {
       unset($fields['billing']['billing_postcode']);
       unset($fields['billing']['billing_address_1']);
       unset($fields['billing']['billing_state']);
    }
    return $fields;
}
add_filter('woocommerce_checkout_fields', 
'premove_billing_checkout_fields', 990 );

This code is working, but to hide the fields I need to refresh the page.
How can I hide the fields using Ajax?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Update 4 (made on June 2018)
– Added a delay on initialization specifically for Woocommerce 3.4.x.
– Solved a bug when shipping address checkbox is enabled.
– Enhanced lighter and more effective jQuery code.
– Added conditional fields validation

You don’t need any Ajax to achieve this. The first function will make all necessary checkout fields not “required”, as this is necessary to be able to conditionally show / hide checkout fields. The second function (mostly jQuery), will show / hide your desired fields depending on the chosen shipping method.

// Conditional Show hide checkout fields based on chosen shipping methods
add_action( 'wp_footer', 'custom_checkout_field_script' );
function custom_checkout_field_script() {

    // HERE your shipping methods rate IDs
    $local_pickup = 'local_pickup:20';
    $pickpoint = 'wc_custom_shipping_pickpoint';

    $required_text = esc_attr__( 'required', 'woocommerce' );
    $required_html = '<abbr class="required" title="' . $required_text . '">*</abbr>';
    ?>
    <script>
        jQuery(function($){
            var ism = 'input[name^="shipping_method"]',         ismc = ism+':checked',
                csa = 'input#ship-to-different-address-checkbox',
                rq = '-required',       vr = 'validate'+rq,     w = 'woocommerce',      wv = w+'-validated',
                iv = '-invalid',        fi = '-field',          wir = w+iv+' '+w+iv+rq+fi,
                b = '#billing_',        s = '#shipping_',       f = '_field',
                a1 = 'country',     a2 = 'address_1',   a3 = 'address_2',   a4 = 'postcode',    a5 = 'state',
                b1 = b+a1+f,        b2 = b+a2+f,        b3 = b+a3+f,        b4 = b+a4+f,        b5 = b+a5+f,
                s1 = s+a1+f,        s2 = s+a2+f,        s3 = s+a3+f,        s4 = s+a4+f,        s5 = s+a5+f,
                pickPoint = '<?php echo $pickpoint; ?>',        localPickup = '<?php echo $local_pickup; ?>';

            // Utility function to shows or hide checkout fields
            function showHide( action='show', selector='' ){
                if( action == 'show' )
                    $(selector).show(function(){
                        $(this).addClass(vr);
                        $(this).removeClass(wv);
                        $(this).removeClass(wir);
                        if( $(selector+' > label > abbr').html() == undefined )
                            $(selector+' label').append('<?php echo $required_html; ?>');
                    });
                else
                    $(selector).hide(function(){
                        $(this).removeClass(vr);
                        $(this).removeClass(wv);
                        $(this).removeClass(wir);
                        if( $(selector+' > label > abbr').html() != undefined )
                            $(selector+' label > .required').remove();
                    });
            }

            // Initializing at start after checkout init (Based on the chosen shipping method)
            setTimeout(function(){
                if( $(ismc).val() == pickPoint ) // Chosen "Pick point" (Hiding "Delivery")
                {
                    showHide('show',b1 ); // Country
                    showHide('hide',b2 ); // Address 1
                    showHide('hide',b3 ); // Address 2
                    showHide('hide',b4 ); // Postcode
                    showHide('hide',b5 ); // State
                }
                else if( $(ismc).val() == localPickup ) // Choosen "Local pickup" (Hidding "Take away")
                {
                    showHide('hide',b1);
                    showHide('show',b2);
                    showHide('show',b3);
                    showHide('hide',b4);
                    showHide('hide',b5);
                }
                else
                {
                    showHide('show',b1);
                    showHide('show',b2);
                    showHide('show',b3);
                    showHide('show',b4);
                    showHide('show',b5);
                }
            }, 100);

            // When shipping method is changed (Live event)
            $( 'form.checkout' ).on( 'change', ism, function() {
                if( $(ismc).val() == pickPoint )
                {
                    showHide('show',b1);
                    showHide('hide',b2);
                    showHide('hide',b3);
                    showHide('hide',b4);
                    showHide('hide',b5);

                    if( $(csa).prop('checked') ) {
                        showHide('show',s1);
                        showHide('hide',s2);
                        showHide('hide',s3);
                        showHide('hide',s4);
                        showHide('hide',s5);
                    }
                }
                else if( $(ismc).val() == localPickup )
                {
                    showHide('hide',b1);
                    showHide('show',b2);
                    showHide('show',b3);
                    showHide('hide',b4);
                    showHide('hide',b5);

                    if( $(csa).prop('checked') ) {
                        showHide('hide',s1);
                        showHide('show',s2);
                        showHide('show',s3);
                        showHide('hide',s4);
                        showHide('hide',s5);
                    }
                }
                else
                {
                    showHide('show',b1);
                    showHide('show',b2);
                    showHide('show',b3);
                    showHide('show',b4);
                    showHide('show',b5);

                    if( $(csa).prop('checked') ) {
                        showHide('show',s1);
                        showHide('show',s2);
                        showHide('show',s3);
                        showHide('show',s4);
                        showHide('show',s5);
                    }
                }
            });

            // When "shipping to different address" is changed (Live event)
            $(csa).click( function() {
                if( $(ismc).val() == pickPoint && $(this).prop('checked') )
                {
                    showHide('show',b1);
                    showHide('hide',b2);
                    showHide('hide',b3);
                    showHide('hide',b4);
                    showHide('hide',b4);

                    showHide('show',s1);
                    showHide('hide',s2);
                    showHide('hide',s3);
                    showHide('hide',s4);
                    showHide('hide',s5);
                }
                else if( $(ismc).val() == localPickup && $(this).prop('checked') )
                {
                    showHide('hide',b1);
                    showHide('show',b2);
                    showHide('show',b3);
                    showHide('hide',b4);
                    showHide('hide',b4);

                    showHide('hide',s1);
                    showHide('show',s2);
                    showHide('show',s3);
                    showHide('hide',s4);
                    showHide('hide',s5);
                }
                else
                {
                    showHide('show',b1);
                    showHide('show',b2);
                    showHide('show',b3);
                    showHide('show',b4);
                    showHide('show',b4);

                    showHide('show',s1);
                    showHide('show',s2);
                    showHide('show',s3);
                    showHide('show',s4);
                    showHide('show',s5);
                }
            });
        });
    </script>
    <?php
}

// Checkout conditional fields validation
add_action('woocommerce_checkout_process', 'wps_select_checkout_field_process');
function wps_select_checkout_field_process() {
    // HERE your shipping methods rate IDs
    $local_pickup = 'local_pickup:20';
    $pickpoint    = 'wc_custom_shipping_pickpoint';


    $chosen_shipping_method = WC()->session->get( 'chosen_shipping_methods' )[0];
    $billing                = '<strong> ' . __('Billing', 'woocommerce') . ' ';
    $shipping               = '<strong> ' . __('Shipping', 'woocommerce') . ' ';
    $country                = __('country.', 'woocommerce');
    $address1               = __('address.', 'woocommerce');
    $postcode               = __('postcode.', 'woocommerce');
    $state                  = __('state.', 'woocommerce');
    $end_text               = '</strong> '. __('is a required field.', 'woocommerce');

    if( $chosen_shipping_method == $local_pickup ) {
        if( empty($_POST['billing_address_1']) )
            wc_add_notice( $billing . $address1 . $end_text, 'error' );

        if( $_POST['ship_to_different_address'] ){
            if( empty($_POST['shipping_address_1']) )
                wc_add_notice( $shipping . $address1 . $end_text, 'error' );
        }
    }
    elseif( $chosen_shipping_method == $pickpoint ) {
        if( empty($_POST['billing_country']) )
            wc_add_notice( $billing . $country . $end_text, 'error' );

        if( $_POST['ship_to_different_address'] ){
            if( empty($_POST['shipping_country']) )
                wc_add_notice( $shipping . $country . $end_text, 'error' );
        }
    }
    else {
        if( empty($_POST['billing_country']) )
            wc_add_notice( $billing . $country . $end_text, 'error' );

        if( empty($_POST['billing_address_1']) )
            wc_add_notice( $billing . $address1 . $end_text, 'error' );

        if( empty($_POST['billing_postcode']) )
            wc_add_notice( $billing . $postcode . $end_text, 'error' );

        if( empty($_POST['billing_state']) )
            wc_add_notice( $billing . $state . $end_text, 'error' );

        if( $_POST['ship_to_different_address'] ){
            if( empty($_POST['shipping_country']) )
                wc_add_notice( $shipping . $country . $end_text, 'error' );

            if( empty($_POST['shipping_address_1']) )
                wc_add_notice( $shipping . $address1 . $end_text, 'error' );

            if( empty($_POST['shipping_postcode']) )
                wc_add_notice( $shipping . $postcode . $end_text, 'error' );

            if( empty($_POST['shipping_state']) )
                wc_add_notice( $shipping . $state . $end_text, 'error' );
        }
    }
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

This is tested and works on WooCommerce 3+

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply