skip to Main Content

My HTML code (delivery methods list of radio buttons) is:

<ul id="shipping_method" class="woocommerce-shipping-methods">
    <li>
        <input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_local_pickup8" value="local_pickup:8" class="shipping_method" checked="checked"><label for="shipping_method_0_local_pickup8">Local pickup</label>
    </li>
    <li>
        <input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_edostavka-package-door-stock7138" value="edostavka-package-door-stock:7:138" class="shipping_method"><label for="shipping_method_0_edostavka-package-door-stock7138">Postamat: <span class="woocommerce-Price-amount amount">265&nbsp;<span class="woocommerce-Price-currencySymbol">₽</span></span></label>
    </li>
    <li>
        <input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_flat_rate1" value="flat_rate:1" class="shipping_method"><label for="shipping_method_0_flat_rate1">Courier delivery <span class="woocommerce-Price-amount amount">350&nbsp;<span class="woocommerce-Price-currencySymbol">₽</span></span></label>
    </li>
</ul>

It cannot changed (Woocommerce HTML generation). At least I do not want to change it.

My task is add Javascript handlers on selection change event:

jQuery(document).ready(function($){
    let methods = jQuery('.shipping_method’);
    methods.each(function(index) {
        $(this).bind('change', function() {
            alert('Change event fired for ' + this.val());
        });
    });
});

Handlers are not fired when delivery method (radio button with class == ’shipping_method’) changed.

Change handler for whole list of radio also doesn’t work:

methods.bind('change', function() {
    alert(this.val());
});

What’s wrong?

3

Answers


  1. Chosen as BEST ANSWER

    @Rory: Awesome! Yes, your advice works great!


  2. Firstly in your JS you’re using the wrong type of apostrophe, instead of ', which is unsupported in JS, to close the jQuery selector string.

    let methods = jQuery('.shipping_method’); // change the last apostrophe on this line
    

    Secondly, in the change event handler this refers to the Element object which has no val() method. You need to call it on a jQuery object, so use $(this).val() instead.

    Lastly, bind() is deprecated and should not be used. Use on() instead, and make sure you’re using an up to date version of jQuery, ideally at least something 3.x. You also don’t need the each() loop, as you can bind event handlers to a collection of Elements in a single jQuery object. Try this:

    jQuery(document).ready(function($) {
      $('.shipping_method').on('change', function() {
        console.log('Change event fired for ' + $(this).val());
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <ul id="shipping_method" class="woocommerce-shipping-methods">
      <li>
        <input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_local_pickup8" value="local_pickup:8" class="shipping_method" checked="checked"><label for="shipping_method_0_local_pickup8">Local pickup</label>
      </li>
      <li>
        <input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_edostavka-package-door-stock7138" value="edostavka-package-door-stock:7:138" class="shipping_method"><label for="shipping_method_0_edostavka-package-door-stock7138">Postamat: <span class="woocommerce-Price-amount amount">265&nbsp;<span class="woocommerce-Price-currencySymbol">₽</span></span></label>
      </li>
      <li>
        <input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_flat_rate1" value="flat_rate:1" class="shipping_method"><label for="shipping_method_0_flat_rate1">Courier delivery <span class="woocommerce-Price-amount amount">350&nbsp;<span class="woocommerce-Price-currencySymbol">₽</span></span></label>
      </li>
    </ul>

    It’s worth noting that both of these issues were visible in the console, which is where you should look first when trying to debug JS logic.

    Login or Signup to reply.
  3. Just so you know there’s a way to get which shipping method is clicked using a WooCommerce hook:

     function prefix_detect_chosen_shipping_method(){
        
                if ( ! defined( 'DOING_AJAX' ) ){
                    return;
                }
        
                $chosen_method = WC()->session->get( 'chosen_shipping_methods' );
        
                if( ! is_array( $chosen_method ) ){
                    return;
                }
        
                $chosen_method = $chosen_method[0];
    
                // Do something with the chosen method.
        
            }
    
    add_action( 'woocommerce_cart_calculate_fees', 'prefix_detect_chosen_shipping_method', 10, 2 );
    

    However, this wouldn’t work for me because I needed to fire some javascript based on the selected shipping method. Here’s how I accomplished it using some JavaScript that is present only on the checkout page:

    (function( $ ) {
        'use strict';
    
        $( document ).ready( function(){
    
            $( document.body ).on( 'updated_checkout', () =>{
    
                let prefixShippingMethods = document.querySelectorAll('#shipping_method .shipping_method');
    
                for (const prefixShippingMethod of prefixShippingMethods ){
    
                    // We have to check for the hidden type as well because if only one shipping method is available WC doesn't show radio buttons.
                    if( lpacShippingMethod.checked || lpacShippingMethod.type === 'hidden' ){
                        // Do something now that you know which method is checked
                        // NOTE! The shipping method name will not be exact, you will have to use indexOf() for comparisons
    
                        if( prefixShippingMethod.value.indexOf('local_pickup') ){
                            //This will happen when Local Pickup is selected
                        }
                        
                    }
    
                }
    
    
            });
    
        });
    
    })( jQuery );
    

    You can clean up JS as you wish, I couldn’t detect this event in vanilla JS, thats why I’m using jQuery here.

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