Custom checkout field and shipping methods ajax in

2019-08-01 01:18发布

This issue is going to make me go postal pretty soon....

In Woocommerce Checkout , I needed to add a Custom field in the address. This extra field is for function calculate_shipping( $package = array())

Now Clearly woocommerce / wordpress don't allow access to these custom fields within this function call.. don't understand why but we move along..

So the solution would be jQuery right? .. not so fast .. Every single example does not return the value back into the woocommerce environment .. not one ..

So on to the code I have so far down this rabbit hole for a single field value......

//We first add the field to the checkout form
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields');

function custom_override_checkout_fields( $fields ) {
     $fields['billing']['billing_area'] = array(
         'label'     => __('Area', 'woocommerce'),
         'placeholder'   => _x('Area', 'placeholder', 'woocommerce'),
         'required'  => true,
         'class'     => array('form-row-wide' ),
         'clear'     => true,
         'priority' => 61
     );

     return $fields;
}

// we load the scripts and the ajax callback functions

add_action( 'wp_enqueue_scripts', 'so18550905_enqueue_scripts' );
add_action( 'wp_ajax_myaction', 'so18550905_wp_ajax_function' );
add_action( 'wp_ajax_nopriv_myaction' , 'so18550905_wp_ajax_function' );

function so18550905_enqueue_scripts(){
    wp_register_script( 'ajaxHandle', plugins_url() . '/miguel-shipping/test.js', array('jquery'), '1.0', true );
    wp_enqueue_script( 'ajaxHandle' );
    wp_localize_script( 'ajaxHandle', 'ajax_object', array( 'ajaxurl' => admin_url( 'admin_ajax.php' ) ) );
}

function so18550905_wp_ajax_function(){
  //this function should be called but it is not for some reason..
  $testingitouthere=$_POST['my_billing_area'] ;
  file_put_contents('blablablabla.txt', print_r($testingitouthere,true));
  wp_die(); 
}

The JS Code:

jQuery(document).ready( function($){

    $('#billing_area').change(function () {
        var billing_area = $('#billing_area').val();
        console.log(billing_area);

    $.ajax({
        url: ajax_object.ajaxurl, // this is the object instantiated in wp_localize_script function
        type: 'POST',
        data:{
            action: 'myaction', 
            my_billing_area: billing_area 
        },
        success: function( data ){
        //Do something with the result from server
        console.log( data );
        }
    });
    return false;
});

});

The problem is that the function in the php called

so18550905_wp_ajax_function()

just never gets triggered.. I'm writing to file in that function (before someone asks) solely for testing only .. once I get to that point i'll carry on coding from there... The Jquery is logging to console aswell..

1条回答
三岁会撩人
2楼-- · 2019-08-01 02:17

Try the following revisited code is based on your provided code that will add in a custom WC_Session the value of the Billing Area field through Ajax.

Then you will be able to get the live value using: $value = WC()->session->get('billing_area'); in a custom function hooked in woocommerce_shipping_packages filter hook located in WC_Shipping method calculate_shipping() as you asked.

The code:

// Add a custom billing field
add_filter( 'woocommerce_billing_fields', 'add_custom_billing_field', 20, 1 );
function add_custom_billing_field($billing_fields) {

    $billing_fields['billing_area'] = array(
        'label'     => __('Area', 'woocommerce'),
        'placeholder'   => _x('Fill in your area', 'placeholder', 'woocommerce'),
        'required'  => true,
        'class'     => array('form-row-wide' ),
        'clear'     => true,
        'priority' => 65
    );
    return $billing_fields;
}

// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_billing_area', 'get_ajax_billing_area' );
add_action( 'wp_ajax_nopriv_billing_area', 'get_ajax_billing_area' );
function get_ajax_billing_area() {
    if ( isset($_POST['billing_area']) ){
        WC()->session->set('billing_area', esc_attr($_POST['billing_area']));
        echo $_POST['billing_area'];
    }
    die();
}

// Refreshing session shipping methods data (Mandatory)
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
    $bool = true;
    if ( WC()->session->get('billing_area' ) != '' ) $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();
}

// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_billing_area_script' );
function checkout_billing_area_script() {
    // Only checkout page
    if( is_checkout() && ! is_wc_endpoint_url() ):

    // Remove "billing_area" custom WC session on load
    if( WC()->session->get('billing_area') ){
        WC()->session->__unset('billing_area');
    }
    // jQuery Ajax code below
    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof wc_checkout_params === 'undefined')
            return false;

        var a = '#billing_area', f = 'form.checkout';

        // Ajax function
        function checkBArea( value ){
             $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': 'billing_area',
                    'billing_area': value,
                },
                success: function (result) {
                    $('body').trigger('update_checkout');
                    console.log(result); // For testing (to be removed)
                }
            });
        }

        // On start
        if( $(a).val() != '' )
            checkBArea($(a).val());

        // On change event
        $(f).on('change', a, function() {
            checkBArea($(this).val());
        });
    });
    </script>
    <?php
    endif;
}

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


Similar or related threads:

查看更多
登录 后发表回答