This post is a follow-up on another question:
Dynamic select field options based on selected day in Woocommerce checkout
So, with this answer help, I did manage to build a dynamic select field on the checkout page, which had changing options, based on the chosen date from a Datepicker. This solution works perfectly on the author test server…
However on my site, the code give some problems if the pickeded date is in May or October. Actually it seems that it doesn't work at all.
Those were and are the main requirements:
If Mon-Fri is chosen, pick-up ('delivery_time') every 30 minutes from 10:00 to 18:00
If Sat-Sun is chosen, pick-up ('delivery_time') every 30 minutes from 10:00 to 15:00
Only first Sundays in month is available. Other Sundays, no options available. (new requirement added in April and was working)
Can this have anything to do with my installation? I've tried to disable all plugins and deactivated localizer for Datepicker as well.
Following is the code for Dynamic select:
/**
*
* 2018-04-16
* Picking date and time
* Dynamic select based on selected day
*
*/
add_action( 'wp_enqueue_scripts', 'enabling_date_picker' );
function enabling_date_picker() {
// Only on front-end and checkout page
if( is_admin() || ! is_checkout() ) return;
// Load the datepicker jQuery-ui plugin script
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_style('jquery-ui', "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/smoothness/jquery-ui.css", '', '', false);
}
// Datepicker field and select time field
add_action( 'woocommerce_before_order_notes', 'datepicker_custom_field' );
function datepicker_custom_field($checkout) {
echo '<h3>' . __('Hvornår vil du hente din ordre?') . '</h3>';
echo '<div id="date-time-wrapper">';
woocommerce_form_field('delivery_date', array(
'type' => 'text',
'class'=> array('delivery-date-class form-row-first'),
'label' => __('Vælg dato for afhentning'),
'required' => true,
//'placeholder' => __('Pick a date')
), $checkout->get_value('delivery_date') );
$options = array('' => __('Afhentning kl.') );
woocommerce_form_field( 'delivery_time', array(
'type' => 'select',
'class' => array('delivery-time-class form-row-last'),
'label' => __('Vælg tidspunkt for afhentning'),
'required' => true,
'options' => $options,
), $checkout->get_value( 'delivery_time' ) );
// Restricted options array
$options1 = array(
'10:00' => __( '10:00' ),
'10:30' => __( '10:30' ),
'11:00' => __( '11:00' ),
'11:30' => __( '11:30' ),
'12:00' => __( '12:00' ),
'12:30' => __( '12:30' ),
'13:00' => __( '13:00' ),
'13:30' => __( '13:30' ),
'14:00' => __( '14:00' ),
'14:30' => __( '14:30' ),
'15:00' => __( '15:00' ),
);
// The other part of options array
$options2 = array(
'15:30' => __( '15:30' ),
'16:00' => __( '16:00' ),
'16:30' => __( '16:30' ),
'17:00' => __( '17:00' ),
'17:30' => __( '17:30' ),
'18:00' => __( '18:00' ),
);
// The third part of options array
$options3 = array(
'Sundays_Closed' => __( 'Åbent første søndag i måneden'),
);
// Merging options arrays
$options1 = array_merge($options, $options1); // Partial
$options = array_merge($options1,$options2); // Full
echo '<br clear="all"></div>';
?>
<script language="javascript">
jQuery( function($){
var a = <?php echo json_encode($options); ?>,
b = <?php echo json_encode($options1); ?>,
e = <?php echo json_encode($options3); ?>,
c = new Date(),
s = 'select#delivery_time';
// Utility function to fill dynamically the select field options
function dynamicSelectOptions( opt ){
var o = '';
$.each( opt, function( key, value ){
o += '<option value="'+key+'">'+value+'</option>';
});
$(s).html(o);
}
// Once DOM is loaded
//Only open first Sunday in month
if( c.getDay() == 0 && c.getDate() > 7 ){
dynamicSelectOptions( e );
}
else if( c.getDay() == 6 || c.getDay() == 0){
dynamicSelectOptions( b );
}
else
dynamicSelectOptions( a );
// Select time to selectWoo
$(s).selectWoo();
// Datepicker
$('#delivery_date').datepicker({
dateFormat: 'd MM, y',
minDate:1,
maxDate:new Date(2018, 12),
onSelect: function(){
// Live event: On selected date event
var d = new Date($(this).val());
//Only first Sunday in month open
if( d.getDay() == 0 && d.getDate() > 7 ){
dynamicSelectOptions( e );
}
else if( d.getDay() == 6 || d.getDay() == 0){
dynamicSelectOptions( b );
}
else
dynamicSelectOptions( a );
}
}).parent().after('<div id="order-desc"></div>');
});
</script>
<?php
}
I have made some little changes in your code:
I Have moved the jQuery script in footer at the end (as it's the best way for jQuery).
I have embed all your select options (all different arrays) in a separate utility function.
But I am not sure that it will work on your server configuration... I hope that this will solve the problem (that I don't have on my both test servers configs).
Your code revisited code:
add_action( 'wp_enqueue_scripts', 'enabling_date_picker' );
function enabling_date_picker() {
// Only on front-end and checkout page
if( is_admin() || ! is_checkout() ) return;
// Load the datepicker jQuery-ui plugin script
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_style('jquery-ui', "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/smoothness/jquery-ui.css", '', '', false);
}
// Utility function (with all option arrays)
function select_options( $type = '' ){
$options = array('' => __('Afhentning kl.') ); // Default start
$options1 = array( // Restricted options array
'10:00' => __( '10:00' ), '10:30' => __( '10:30' ), '11:00' => __( '11:00' ),
'11:30' => __( '11:30' ), '12:00' => __( '12:00' ), '12:30' => __( '12:30' ),
'13:00' => __( '13:00' ), '13:30' => __( '13:30' ), '14:00' => __( '14:00' ),
'14:30' => __( '14:30' ), '15:00' => __( '15:00' ),
);
$options2 = array( // complementary options array
'15:30' => __( '15:30' ), '16:00' => __( '16:00' ), '16:30' => __( '16:30' ),
'17:00' => __( '17:00' ), '17:30' => __( '17:30' ),'18:00' => __( '18:00' ),
);
if( $type == 'partial' ){
return array_merge($options, $options1); // Partial;
} elseif ( $type == 'full' ){
return array_merge($options,$options1,$options2); // Full
} elseif ( $type == 'close' ){
return array( 'Sundays_Closed' => __( 'Åbent første søndag i måneden') ); // Sundays closed
} else {
return $options; // Default (start)
}
}
// Checkout Datepicker field and select time field
add_action( 'woocommerce_before_order_notes', 'datepicker_custom_field' );
function datepicker_custom_field($checkout) {
echo '<h3>' . __('Hvornår vil du hente din ordre?') . '</h3>';
echo '<div id="date-time-wrapper">';
woocommerce_form_field('delivery_date', array(
'type' => 'text',
'class'=> array('delivery-date-class form-row-first'),
'label' => __('Vælg dato for afhentning'),
'required' => true,
//'placeholder' => __('Pick a date')
), $checkout->get_value('delivery_date') );
$options = select_options();
woocommerce_form_field( 'delivery_time', array(
'type' => 'select',
'class' => array('delivery-time-class form-row-last'),
'label' => __('Vælg tidspunkt for afhentning'),
'required' => true,
'options' => $options,
), $checkout->get_value( 'delivery_time' ) );
echo '<br clear="all"></div>';
}
add_action( 'wp_footer', 'date_picker_js_script' );
function date_picker_js_script() {
// Only on checkout page
if( ! is_checkout() ) return;
?>
<script language="javascript">
jQuery( function($){
var a = <?php echo json_encode(select_options('full')); ?>,
b = <?php echo json_encode(select_options('partial')); ?>,
e = <?php echo json_encode(select_options('close')); ?>,
c = new Date(),
s = 'select#delivery_time';
// Utility function to fill dynamically the select field options
function dynamicSelectOptions( opt ){
var o = '';
$.each( opt, function( key, value ){
o += '<option value="'+key+'">'+value+'</option>';
});
$(s).html(o);
}
// ===> Just for testing - To be removed
console.log('Day: '+c.getDay()+' | Date: '+c.getDate());
// 1. Once DOM is loaded
if( c.getDay() == 0 && c.getDate() > 7 ){ // Only open first Sunday in month
dynamicSelectOptions( e );
} else if( c.getDay() == 6 || c.getDay() == 0){ // Weekends
dynamicSelectOptions( b );
} else { // all others days
dynamicSelectOptions( a );
}
// Select time to selectWoo
$(s).selectWoo();
// Datepicker
$('#delivery_date').datepicker({
dateFormat: 'd MM, y',
minDate:1,
maxDate:new Date(2018, 12),
onSelect: function(){
// On live calendar event: On selected date event
var d = new Date($(this).val());
// ===> Just for testing - To be removed
console.log('Day: '+d.getDay()+' | Date: '+d.getDate());
if( d.getDay() == 0 && d.getDate() > 7 ) { // Only first Sunday in month open
dynamicSelectOptions( e );
} else if( d.getDay() == 6 || d.getDay() == 0) { // Weekends
dynamicSelectOptions( b );
} else { // all others days
dynamicSelectOptions( a );
}
}
}).parent().after('<div id="order-desc"></div>');
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme).
I have tested your code on 2 different test servers with WooCommerce 3.2.x and 3.3.x, and it works (tested that on different browsers and platforms).
This issue could be related to your theme, some plugin or other customizations made by you.
Related
I am not sure why my custom FacetWP facet will not render on the front end of WordPress
I need a custom FacetWP dropdown that shows the user options such as: today, tomorrow, December by taking in two acf fields of
event_date_start and event_date_end and filtering the posts based on this range.
I have attempted to set up the facet as follows:
First, create a custom facet type in FacetWP by adding this code to functions.php file:
add_filter( 'facetwp_facet_types', function( $types ) {
$types['custom_dropdown'] = array(
'label' => 'Custom Dropdown',
'query_type' => 'custom',
);
return $types;
});
Next, the custom query code in functions.php file:
add_filter( 'facetwp_query_args', function( $query_args, $renderer ) {
$params = $renderer->$params;
if ( 'custom_dropdown' == $params['facet']['type'] ) {
$selected = $params['selected_values'][0];
switch ( $selected ) {
case 'today':
$selected_date = strtotime( 'today' );
break;
case 'tomorrow':
$selected_date = strtotime( 'tomorrow' );
break;
case 'December':
$selected_date = strtotime( 'December' );
break;
}
$query_args['meta_query'][] = array(
'relation' => 'AND',
array(
'key' => 'event_date_start',
'value' => $selected_date,
'compare' => '<=',
'type' => 'NUMERIC',
),
array(
'key' => 'event_date_end',
'value' => $selected_date,
'compare' => '>=',
'type' => 'NUMERIC',
),
);
}
return $query_args;
}, 10, 2 );
Add the custom dropdown options to the facet settings in functions.php file:
add_filter( 'facetwp_render_output', function( $output, $params ) {
if ( 'custom_dropdown' == $params['facet']['type'] ) {
$output = '<select>';
$options = array( 'today', 'tomorrow', 'December' );
foreach ( $options as $option ) {
$selected = ( $option == $params['selected_values'][0] ) ? ' selected' : '';
$output .= '<option value="' . $option . '"' . $selected . '>' . $option . '</option>';
}
$output .= '</select>';
}
return $output;
}, 10, 2 );
I have placed this shortcode on the front end:
[facetwp facet="custom_dropdown"]
I have also tried to set the Date Source to be 'custom' but this does not work either:
add_filter( 'facetwp_facet_sources', function( $sources ) {
$sources['custom'] = array(
'label' => 'Custom Values',
'choices' => array(
'today' => 'Today',
'tomorrow' => 'Tomorrow',
'December' => 'December'
),
'props' => array(
'data_type' => 'custom'
)
);
return $sources;
});
If someone knows what the issue could be I would really appreciate if someone can help.
I am populating a dropdown from a woocommerce_form_field() as shown below:
// Add additional items to array
$options = array(
0 => __( 'Select an option...', 'woocommerce' ),
1 => __( 'No Compressor & Bracket ', 'woocommerce')
) + $options;
// Add select field
woocommerce_form_field( 'compressor-options', array(
'type' => 'select',
'label' => __( 'Add Compressor & Bracket', $domain ),
'required' => false,
'options' => $options,
),'' );
echo '<p>Number of Compressor & Bracket options: ' . count( $options ) . '</p>';
I would like to change the SKU of the main product depending on the selection made by the user. I am currently unaware of how to do so.
I have a function to change the SKU, but it does not take in if the user makes a selection.
function change_current_sku() {
global $product;
if ( ! isset( $POST['compressor-options'] ) ) {
echo '<div><br></div>';
echo $product->get_sku() . ' (EX)';
}
}
add_action( 'woocommerce_after_add_to_cart_button', 'change_current_sku' );
Is there a way to have an onchange() on the woocommerce_form_field?
When it comes to simple type products only, then ajax per se is not necessary and just jQuery will do. So it depends on your specific requirements.
So you get:
function action_woocommerce_before_add_to_cart_button() {
// Some random options
$random_options = array( 2 => 'abc', 3 => 'def', 4 => '(ghi)', 5 => 'jkl' );
// Add additional items to array
$options = array(
0 => __( 'Select an option...', 'woocommerce' ),
1 => __( 'No Compressor & Bracket ', 'woocommerce')
) + $random_options;
// Add select field
woocommerce_form_field( 'compressor-options', array(
'type' => 'select',
'label' => __( 'Add Compressor & Bracket', 'woocommerce' ),
'required' => false,
'options' => $options,
),'' );
echo '<p>Number of Compressor & Bracket options: ' . count( $options ) . '</p>';
?>
<script type="text/javascript">
jQuery( function($) {
// On change
$( document ).on( 'change', '#compressor-options', function () {
var suffix = $( 'option:selected', this ).text();
// Append
$( '.my-product-sku .sku-suffix' ).text( suffix );
});
});
</script>
<?php
}
add_action( 'woocommerce_before_add_to_cart_button', 'action_woocommerce_before_add_to_cart_button' );
function action_woocommerce_after_add_to_cart_button() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
echo '<p class="my-product-sku">' . $product->get_sku() . ': ' . '<span class="sku-suffix"></p>';
}
}
add_action( 'woocommerce_after_add_to_cart_button', 'action_woocommerce_after_add_to_cart_button', 10 );
I am using xdsoft date time picker at woo-commerce checkout and need to add an extra fee if a user selects the same day or tomorrow on the date time picker. I am not sure how to go with this and would appreciate it if someone can help me with this.
Below is the code I am using currently and it is working fine for the situation.
function date_time_picker( $checkout ) {
woocommerce_form_field( 'delivery_date', array(
'type' => 'text',
'class' => array('form-row-wide'),
'id' => 'datepicker',
'required' => true,
'label' => __('Select Delivery Date'),
'placeholder' => __('Click to select date'),
));
}
add_action( 'woocommerce_after_order_notes', 'date_time_picker' );
function validate_new_checkout_fields() {
if ( isset( $_POST['delivery_date'] ) && empty( $_POST['delivery_date'] ) ) wc_add_notice( __( 'Please select the Delivery Date' ), 'error' );
}
add_action( 'woocommerce_checkout_process', 'validate_new_checkout_fields' );
function enable_datepicker() {
?>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>
<?php
}
add_action( 'woocommerce_after_checkout_form', 'enable_datepicker', 10 );
function load_calendar_dates( $available_gateways ) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
jQuery.datetimepicker.setLocale('en');
var currentDate = new Date();
var minutes = currentDate.getMinutes();
var m = (Math.ceil(minutes/30) * 30) % 60;
currentDate.setMinutes(m);
jQuery('#datepicker').datetimepicker({
beforeShowDay: $.datepicker.noWeekends,
format: 'Y/m/d H:i:s',
minDate: 0,
minTime: '8:00',
step: "30",
allowTimes:[
'09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30',
'13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'
]
});
});
</script>
<?php
}
add_action( 'woocommerce_after_checkout_form', 'load_calendar_dates', 20 );
You can use woocommerce_cart_calculate_fees to add fees.
Use add_fee() function to add fees. You need to calculate datediff for today and tomorrow day. furthermore, you can see PHP: How to check if a date is a today, yesterday or tomorrow Try the below code.
/**
* Add a standard $ value surcharge to all transactions in cart/checkout
*/
function wc_add_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
// change the $fee to set the surcharge to a value to suit
parse_str($_POST['post_data'], $post_data);
if( isset( $post_data['delivery_date'] ) && $post_data['delivery_date'] != '' ){
$current = strtotime(date("Y-m-d"));
$date = strtotime($post_data['delivery_date']);
$datediff = $date - $current;
$difference = floor($datediff/(60*60*24));
if( $difference == 0 || $difference == 1 ){
$fee = 5.00; // today and tomorrow
$woocommerce->cart->add_fee( 'Fast delivery charge', $fee, true, 'standard' );
} else {
// other day
$fees = WC()->cart->get_fees();
foreach ($fees as $key => $fee) {
if($fees[$key]->name === __( "Fast delivery charge")) {
unset($fees[$key]);
}
}
WC()->cart->fees_api()->set_fees($fees);
}
}
}
add_action( 'woocommerce_cart_calculate_fees','wc_add_surcharge' );
function date_time_picker( $checkout ) {
woocommerce_form_field( 'delivery_date', array(
'type' => 'text',
'class' => array('form-row-wide'),
'id' => 'datepicker',
'required' => true,
'label' => __('Select Delivery Date'),
'placeholder' => __('Click to select date'),
));
}
add_action( 'woocommerce_after_order_notes', 'date_time_picker' );
function validate_new_checkout_fields() {
if ( isset( $_POST['delivery_date'] ) && empty( $_POST['delivery_date'] ) ) wc_add_notice( __( 'Please select the Delivery Date' ), 'error' );
}
add_action( 'woocommerce_checkout_process', 'validate_new_checkout_fields' );
In datetimepicker You can use onSelectDate and onSelectTime event to trigger update_checkout
function load_calendar_dates( $available_gateways ) {
?>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
jQuery.datetimepicker.setLocale('en');
var currentDate = new Date();
var minutes = currentDate.getMinutes();
var m = (Math.ceil(minutes/30) * 30) % 60;
currentDate.setMinutes(m);
jQuery('#datepicker').datetimepicker({
beforeShowDay: $.datepicker.noWeekends,
format: 'Y/m/d H:i:s',
minDate: 0,
minTime: '8:00',
step: "30",
allowTimes:[
'09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'
],onSelectDate:function(ct,$i){
$( 'body' ).trigger( 'update_checkout' );
},onSelectTime:function(ct,$i){
$( 'body' ).trigger( 'update_checkout' );
}
});
});
</script>
<?php
}
add_action( 'woocommerce_after_checkout_form', 'load_calendar_dates', 20 );
Save Select Delivery Date and show in Order edit page and emails.
function save_delivery_date_field( $order_id ) {
if ( $_POST['delivery_date'] ) update_post_meta( $order_id, 'delivery_date', esc_attr( $_POST['delivery_date'] ) );
}
add_action( 'woocommerce_checkout_update_order_meta', 'save_delivery_date_field' );
function show_delivery_date_field_order( $order ) {
$order_id = $order->get_id();
if ( get_post_meta( $order_id, 'delivery_date', true ) ) echo '<p><strong>Delivery Date:</strong> ' . get_post_meta( $order_id, 'delivery_date', true ) . '</p>';
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'show_delivery_date_field_order', 10, 1 );
function show_delivery_date_field_emails( $order, $sent_to_admin, $plain_text, $email ) {
if ( get_post_meta( $order->get_id(), 'delivery_date', true ) ) echo '<p><strong>Delivery Date:</strong> ' . get_post_meta( $order->get_id(), 'delivery_date', true ) . '</p>';
}
add_action( 'woocommerce_email_after_order_table', 'show_delivery_date_field_emails', 20, 4 );
I am creating a WooCommerce plugin and I want to display dynamically Sub Areas according to chosen customer city in checkout page.
Here is my code attempt:
add_filter( 'woocommerce_checkout_fields', 'dvs_city_list' );
function dvs_city_list( $fields ) {
$fields["billing"]["billing_city"]["type"] = 'select';
$fields["billing"]["billing_city"]["input_class"] = array(
'state_select' => 'state_select'
);
$fields["billing"]["billing_city"]["options"] = array(
'Lahore' => 'Lahore',
'Karachi' => 'Karachi'
),
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'dvs_area_list' );
function dvs_area_list( $fields ) {
$fields['billing']['billing_area']['label'] = 'Area';
$fields['billing']['billing_area']['required'] = 'True';
$fields["billing"]["billing_area"]["type"] = 'select';
$fields["billing"]["billing_area"]["class"][0] = 'form-row-last';
$fields['billing']['billing_area']['priority'] = 50;
$fields["billing"]["billing_area"]["input_class"] = array(
'state_select' => 'state_select'
);
$city = $_REQUEST['billing_city'];
if ($city == 'Lahore') {
$fields["billing"]["billing_area"]["options"] = array(
'Naval Town' => 'Naval Town',
'Bahria Town' => 'Bahria Town',
'Faisal Town' => 'Faisal Town'
);
}
else ($city == 'Karachi') {
$fields["billing"]["billing_area"]["options"] = array(
'Walton Road' => 'Walton Road',
'Zest Road' => 'Zest Road'
);
}
return $fields;
}
Here is the screenshot
But I am getting this error
Notice:
Undefined index: billing_city in …wp-content/plugins/custom-plugin/index.php on line 35
How to fixed this error? What I am doing wrong?
To synch a custom checkout select field from another select field, it requires to use jQuery.
Also you can merge both functions as they use the same hook.
Below in the first function, we keep your cities / areas settings that we can call everywhere. The last function enable dynamic options changes on the "Billing areas" dropdown depending on the chosen city:
function cities_areas_settings() {
$text_domain = 'woocommerce';
return array(
__('Lahore', $text_domain) => array(
__('Naval Town', $text_domain),
__('Bahria Town', $text_domain),
__('Faisal Town', $text_domain),
),
__('Karachi', $text_domain) => array(
__('Walton Road', $text_domain),
__('Zest Road', $text_domain),
)
);
}
add_filter( 'woocommerce_checkout_fields', 'custom_checkout_fields' );
function custom_checkout_fields( $fields ) {
// Initializing
$text_domain = 'woocommerce';
$option_cities = array();
$lahore_areas = array( '' => __('Choose your area', $text_domain) );
// Load settings and prepare options arrays
foreach( cities_areas_settings() as $city => $areas ) {
$option_cities[$city] = $city;
if( $city === 'Lahore' ) {
foreach( $areas as $area ) {
$lahore_areas[$area] = $area;
}
}
}
// 1. Billing City field
$fields['billing']['billing_city']['type'] = 'select';
$fields['billing']['billing_city']['class'] = array('form-row-first');
$fields['billing']['billing_city']['input_class'] = array('state_select');
$fields['billing']['billing_city']['options'] = $option_cities;
// 2. Billing Area Field
$fields['billing']['billing_area'] = array(
'type' => 'select',
'label' => __('Area', $text_domain),
'class' => array('form-row-last'),
'input_class' => array('state_select'),
'options' => $lahore_areas,
'required' => true,
'default' => '',
'priority' => 50,
);
return $fields;
}
add_action('wp_footer', 'custom_checkout_js_script');
function custom_checkout_js_script() {
if( is_checkout() && ! is_wc_endpoint_url() ) :
// Initializing
$text_domain = 'woocommerce';
$karachi_areas = array( '' => __('Choose your area', $text_domain) );
$settings = cities_areas_settings(); // Load settings
// Prepare 'Karachi' options dropdown
foreach( cities_areas_settings()['Karachi'] as $area ) {
$karachi_areas[$area] = $area;
}
?>
<script language="javascript">
jQuery( function($){
var a = 'select[name="billing_city"]',
b = 'select[name="billing_area"]',
o = <?php echo json_encode($karachi_areas); ?>,
s = $(b).html();
// Utility function to fill dynamically the select field options
function dynamicSelectOptions( opt ){
var options = '';
$.each( opt, function( key, value ){
options += '<option value="'+key+'">'+value+'</option>';
});
$(b).html(options);
}
// On Start (once DOM is loaded)
if ( $(a).val() === 'Karachi' ) {
dynamicSelectOptions( o );
}
console.log($(a).val());
// On billing city change live event
$('form.woocommerce-checkout').on('change', a, function() {
console.log($(this).val());
if ( $(this).val() === 'Karachi' ) {
dynamicSelectOptions( o );
} else {
$(b).html(s);
}
});
});
</script>
<?php
endif;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related: Dynamic synched custom checkout select fields in WooCommerce
i'm creating a woocommerce theme that have multiple product type: Mobile, Tablet, Camera,...
I created products types like this:
add_filter( 'product_type_selector', 'add_mobile_product_type' );
function add_mobile_product_type( $types ){
$types[ 'mobile' ] = __( 'Mobile' );
$types[ 'tablet' ] = __( 'Tablet' );
return $types;
}
add_action( 'plugins_loaded', 'create_mobile_product_type' );
function create_mobile_product_type(){
class WC_Product_Mobile extends WC_Product{
public function __construct( $product ) {
$this->product_type = 'mobile';
parent::__construct( $product );
}
}
class WC_Product_Tablet extends WC_Product{
public function __construct( $product ) {
$this->product_type = 'tablet';
parent::__construct( $product );
}
}
}
and i created some extra fields like this:
add_action( 'woocommerce_product_options_general_product_data', 'mobile_custom_fields' );
function mobile_custom_fields() {
global $woocommerce, $post;
$prefix = 'mobile_';
echo '<div class="options_group">';
woocommerce_wp_select(
array(
'id' => $prefix . 'sim',
'label' => __( 'Sim Count', 'faitell' ),
'options' => array(
'1' => __( '1 Sim', 'faitell' ),
'2' => __( '2 Sim', 'faitell' ),
'3' => __( '3 Sim', 'faitell' )
)
)
);
echo '</div>';
}
The problem is this fields will shown on all product types, how about show some fields for Mobile and some others for Tablet. is there any way?
I couldn't find an easy way to do it in PHP, so I thought to add some Javascript to hide the field when needed.
Therefore your mobile_custom_fields function became:
function mobile_custom_fields() {
global $woocommerce, $post;
$prefix = 'mobile_';
echo '<div class="options_group" id="sim_count_select">';
woocommerce_wp_select(
array(
'id' => $prefix . 'sim',
'label' => __( 'Sim Count', 'faitell' ),
'options' => array(
'1' => __( '1 Sim', 'faitell' ),
'2' => __( '2 Sim', 'faitell' ),
'3' => __( '3 Sim', 'faitell' )
)
)
);
echo '</div>';
?>
<script>
jQuery(document).ready(function($){
$('#product-type').change(function() {
// check if it's selected a mobile or tablet product type
var is_mobile = $.inArray( $(this).val(), ['mobile', 'tablet'] ) > -1;
// toggle div visibility based on previous information
$('#sim_count_select').toggle( is_mobile );
}).trigger('change');
});
</script>
<?php
}
Note the id="sim_count_select" added to your div for easy targeting.
Not the most elegant solution, but it should work.
<div class="options_group">...</div>
add show_if_{$product_type} class alongside the options_group class in the container above. For example, meta box to be showed only in mobile product type add show_if_mobile.