2
votes

I have a small problem with my woocommerce v3.3.5 project. In my checkout I added custom select with the following options: delivery by email, delivery by post.

I have also created several delivery methods

3 for delivery by post

+1 for free by email.

Is it possible to dynamically change the displayed delivery methods based on the option selected in the custom field added?

Here is the code fragment for my custom select field

add_action( 'woocommerce_checkout_before_billing', 'before_billing_fields', 20 );

function before_billing_fields(){
    $checkout = WC()->checkout;

    woocommerce_form_field('delivery_method', array(
        'type' => 'select',
        'options'       => array(
            'blank'     => __( 'Select a delivery method', 'sdm' ),
            'shipping-by-post'  => __( 'Shipping by post', 'sdm' ),
            'shipping-by-email' => __( 'Shipping by email', 'sdm' )
        ),
        'class' => array('delivery_method form-row-wide'),
        'clear'     => true
    ), $checkout->get_value('delivery_method'));
}

add_action('woocommerce_checkout_process', 'wps_select_checkout_field_process');
function wps_select_checkout_field_process() {
    global $woocommerce;

    if ($_POST['delivery_method'] == "blank")
        wc_add_notice( '<strong>Please select a Delivery method</strong>', 'error' );

}

add_filter('woocommerce_email_order_meta_keys', 'wps_select_order_meta_keys');
function wps_select_order_meta_keys( $keys ) {
    $keys['Delivery Method'] = 'delivery_method';
    return $keys;
}

add_action('woocommerce_checkout_update_order_meta', 'checkout_update_order_meta');
function checkout_update_order_meta($order_id)
{

    $delivery_method = $_POST['delivery_method'];
    if (!empty($delivery_method))
        update_post_meta($order_id, 'delivery_method', sanitize_text_field($delivery_method));

}

...and shipping methods: Woocommerce Shipping Methods

1
yes, it is possibleAlice
Forgive me - that is my first question here. In excess of this custom selection, it is a standard wordpress + woocommerce 3.3.5 application. For the moment, I have this project locallyRadek Olejniczak
I added live link. Mail delivery should only show 'Standard' and 'Express', while email should only show free mail delivery.Radek Olejniczak
@RadekOlejniczak… You can not really hide shipping methods on live browser event… instead the jquery code in my answer below will manage changes… try it.LoicTheAztec
@RadekOlejniczak I have just updated my code slightly…LoicTheAztec

1 Answers

1
votes

Update 2

First, woocommerce_checkout_before_billing doesn't exist… So it could be:

  • woocommerce_checkout_before_customer_details
  • woocommerce_checkout_billing.

Then I have changed a bit your first hooked function with the correct hook, because also we need to set a default shipping method on load:

add_action( 'woocommerce_checkout_billing', 'before_billing_fields', 5 );
function before_billing_fields(){
    $checkout = WC()->checkout;

    woocommerce_form_field('delivery_method', array(
        'type' => 'select',
        'options'       => array(
            'blank'     => __( 'Select a delivery method', 'sdm' ),
            'shipping-by-post'  => __( 'Shipping by post', 'sdm' ),
            'shipping-by-email' => __( 'Shipping by email (evoucher)', 'sdm' )
        ),
        'class' => array('delivery_method form-row-wide'),
        'clear'     => true
    ), $checkout->get_value('delivery_method'));

    // Set the default shipping method on load: "Standard" flat rate
    WC()->session->set('chosen_shipping_methods', array('flat_rate:9'));
}

Then the following code will change of shipping method with your custom select field:

// The Jquery script
add_action( 'wp_footer', 'custom_checkout_script' );
function custom_checkout_script() {
    // Only on checkout page
    if( ! is_checkout() && is_wc_endpoint_url( 'order-received' ) )
        return;
    ?>
    <script type="text/javascript">
        jQuery( function($){
            var a = 'select#delivery_method',
                b = 'input[name^="shipping_method[0]"]',
                c = '#shipping_method_0_',
                d = 'flat_rate9', // Default flat Id
                e = 'free_shipping10', // Free shipping Id
                f = 'free_shipping:10'; // Free shipping rate Id

            // Live action event: On Select "delivery_method" change
            $(a).change( function () {
                if($(this).val() == 'shipping-by-email' )
                    $(c+e).prop("checked", true);
                else
                    $(c+d).prop("checked", true);
                $( document.body ).trigger( 'update_checkout' );
            });

            // Live action event: On Shipping method change
            $( 'form.checkout' ).on( 'change', b, function() {
                // If Free shipping is not selected, we change "delivery_method" slect field to "post"
                if( $(this).val() != f )
                    $(a).val('shipping-by-post');
                else
                    $(a).val('shipping-by-email');
            });
        });
    </script>
    <?php
}

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