In my project I'm customizing some of the WooCommerce features.
My "shipping methods" are:
1. delivery
2. take away
I also added a custom field in the checkout page that is a <select>
populated with the valid times for delivery (case "1") or for the take away (case "2").
It may happen that a user selects 2. take away
in the cart page, then selects a time valid for "2", but then changes to 1. delivery
and the selected time may not be valid anymore, neither the option list and the custom field label.
Of course i'm using the woocommerce_checkout_process
hook to warn the user via wc_add_notice()
, but even if the woocommerce_checkout_fields
hook is triggered (that's where i create the select list), the <select>
values are not updated.
I think there is an AJAX call that is related only to the shipping method and doesn't update the other checkout fields, although woocommerce_checkout_fields
hook is triggered.
How to update the custom fields? Do i need some js/jquery/AJAX?
Or: can a custom field be related to a shipping method (and get updated via AJAX with it)? How?
EDIT
Custom field code:
add_filter( 'woocommerce_checkout_fields', 'fty_filter_checkout_fields' );
function my_filter_checkout_fields($fields) {
$must_deliver = WC()->cart->shipping_total > 0.0; // true=deliver, false=take away
// some complex code to calculate time lists omitted, samples array instead:
$delivery_time_list = array(
"deliver 10:00",
"deliver 11:00",
"deliver 12:00",
"deliver 13:00"
);
$takeaway_time_list = array(
"takeaway 10:00",
"takeaway 10:30",
"takeaway 11:00",
"takeaway 11:30",
"takeaway 12:00",
"takeaway 12:30",
"takeaway 13:00",
"takeaway 13:30"
);
// add the new conditional field
if($must_deliver) {
$fields['my_delivery_datetime'] = array(
'my_delivery_time' => array(
'type' => 'select',
'options' => $delivery_time_list,
'required' => true,
'label' => __('Delivery time')
)
);
} else {
$fields['my_delivery_time'] = array(
'my_delivery_time' => array(
'type' => 'select',
'options' => $takeaway_time_list,
'required' => true,
'label' => __('Take away time')
)
);
}
return $fields;
}
an idea of the validation code:
add_action('woocommerce_checkout_process', 'my_checkout_date_time_validation', 30, 1);
function my_checkout_date_time_validation($doh) {
$time = filter_input(INPUT_POST, 'my_delivery_time');
$shipping = filter_input(INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
if(strpos($time, "deliver")!==FALSE && strpos($shipping[0], "local_pickup")!==FALSE) {
wc_add_notice('Please re-select take away time', 'error');
} else if(strpos($time, "takeaway")!==FALSE && strpos($shipping[0], "distance_based_rate")!==FALSE) {
wc_add_notice('Please re-select delivery time', 'error');
}
}
here's about shipping methods;
add_action( 'woocommerce_flat_rate_shipping_add_rate', 'add_distance_based_delivery_rate', 10, 2 );
function add_distance_based_delivery_rate( $method, $rate ) {
$new_rate = $rate;
$new_rate['id'] .= ':' . 'distance_based_rate';
$new_rate['label'] = 'delivery'; // Rename to 'Rushed Shipping'.
// incredibly complex code used to calculate delivery costs omitted
$dist_cost = 1000;
$new_rate['cost'] += $dist_cost;
$method->add_rate( $new_rate );
}
Thanx!
The code provided was mostly un-useful… I have make a lot of changes and optimizations. All my code is commented, it's tested on WooCommerce 3+ and perfectly works.
1) JAVASCRIPT FOR CONDITIONAL CHECKOUT FIELDS LIVE EVENTS
The only way to get the hand on customer live events (browser side) is javascript/jQuery. So this is not easy because WooCommerce use already a lot of javascript/jQuery/Ajax on checkout page…
I have included the javascript code into the hooked function, but you should save it in a separate file and register this script file with classic WordPress registering script function, like in this thread:
Checkout fields: Hiding and showing existing fields
2) USE EXISTING AVAILABLE SHIPPING METHODS (DYNAMIC PRICES CALCULATION):
You don't need to create any shipping rate. You can use:
For each of your shipping zones, enable, set and rename (label name) the 2 methods in Woocommerce > Settings > Shipping:
For the flat rate you can set any minimal amount (that will be overwritten by your calculations)…
3) SAVING THE SHIPPING TIME TO ORDER META DATA:
I have add some code for that and it's save in 2 custom meta fields:
4) DISPLAYING THE CHOSEN SHIPPING TYPE AND TIME IN A METABOX (IN ORDER EDIT PAGES):
I have also add some code for that.
FINALY HERE IS THE CODE:
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on WooCommerce 3+ and works.