In checkout I've made separate city selects for few countries, (their value will go to hidden default text field billing_address_1). City selects I did myself, they are individual.
I also use the popular solution to update all fields using ajax. On change all works fine - when I change the country, all country selects are hidden, and the one city select for chosen country is visible, but it doesn't work on screen load. I'll show only on 2 countries, but there's more, the code is the same for others - simply more fields to hide.
add_action("wp_footer", "add_script_update_shipping_method");
function add_script_update_shipping_method()
{
if (is_checkout()) { ?>
<script>
jQuery(document).ready(function($) {
jQuery('select#billing_city_ua,select#billing_city_pl').select2();
/* DIDN'T HELP
jQuery(window).on('load', function () {
var countryval = jQuery('#billing_country option:selected').val();
jQuery('#billing_country').val(countryval);
});
TO COPY ALL STRINGS FROM CHANGE TOO
*/
$(document.body).on('updated_checkout updated_shipping_method', function(event, xhr, data) {
$('input[name^="shipping_method"]').on('change', function() {
$('.woocommerce-billing-fields__field-wrapper').block({
message: null,
overlayCSS: {
background: '#fff',
'z-index': 1000000,
opacity: 0.3
}
});
});
jQuery('select#billing_country').on('change', function() {
jQuery('select#billing_city_ua, select#billing_city_pl, p#billing_city_field input').val('');
if (jQuery(this).val() == "UA") {
jQuery('select#billing_city_pl').addClass('d-none').removeClass('d-flex').closest('p').hide();
jQuery('select#billing_city_ua').addClass('d-flex').removeClass('d-none').closest('p').show();
}
if (jQuery(this).val() == "PL") {
jQuery('select#billing_city_ua').addClass('d-none').removeClass('d-flex').closest('p').hide();
jQuery('select#billing_city_pl').addClass('d-flex').removeClass('d-none').closest('p').show();
}
});
jQuery("select#billing_city_ua").on("change", function(e) {
let cityval = jQuery("select#billing_city_ua").val();
jQuery(this).find('.woocommerce-billing-fields__field-wrapper p#billing_city_field>span>input').val(cityval);
});
jQuery("select#billing_city_pl").on("change", function(e) {
let cityval = jQuery("select#billing_city_pl").val();
jQuery(this).find('.woocommerce-billing-fields__field-wrapper p#billing_city_field>span>input').val(cityval);
});
var first_name = $('#billing_first_name').val(),
last_name = $('#billing_last_name').val(),
phone = $('#billing_phone').val(),
email = $('#billing_email').val(),
city = $('#billing_city').val(),
cityua = $('#billing_city_ua').val(),
citypl = $('#billing_city_pl').val(),
address = $('#billing_address_1').val(),
postcode = $('#billing_postcode').val(),
country = $('#billing_country').val();
$(".woocommerce-billing-fields__field-wrapper").html(xhr.fragments[".woocommerce-billing-fields"]);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_first_name"]').val(first_name);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_last_name"]').val(last_name);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_phone"]').val(phone);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_email"]').val(email);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_city"]').val(city);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_city_ua"]').val(cityua);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_city_pl"]').val(citypl);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_postcode"]').val(postcode);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_country"]').val(country);
$(".woocommerce-billing-fields__field-wrapper").find('input[name="billing_address_1"]').val(address);
$('.woocommerce-billing-fields__field-wrapper').unblock();
});
});
</script>
<?php }
}
I tried many tricks - to trigger change event on body change, even on hover or scroll just for test. All country selects are visible on page loading, and when you select the country, all works fine. I wanted to re-select already selected value on load - using cityval too. To copy all the code from on,change code before xhr function didn't help. What's the right way?
EDITED - ADDED THE CODE How I added city select fields
add_filter( 'woocommerce_checkout_fields' , 'dropdown' );
// Our hooked in function - $fields is passed via the filter!
function dropdown( $fields ) {
$fields['billing']['billing_city_ua'] = array(
'label' => __('City', 'woocommerce'),
'placeholder' => _x('billing_city_ua', 'Select your city', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide cities-select'),
'clear' => true,
'type' => 'select',
'priority' => 88,
'options' => array(
'' => __('Select city', 'woocommerce' ),
'City1' => __('City1', 'woocommerce' ),
'City2' => __('City2', 'woocommerce' ),
'City3' => __('City3', 'woocommerce' ),
'City4' => __('City4', 'woocommerce' ),
)
);
$fields['billing']['billing_city_pl'] = array(
'label' => __('City', 'woocommerce'),
'placeholder' => _x('billing_city_pl', 'Select your city', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide cities-select'),
'clear' => true,
'type' => 'select',
'priority' => 88,
'options' => array(
'' => __('Select city', 'woocommerce' ),
'City1' => __('City1', 'woocommerce' ),
'City2' => __('City2', 'woocommerce' ),
'City3' => __('City3', 'woocommerce' ),
'City4' => __('City4', 'woocommerce' ),
)
);
return $fields;
}
I have completely revisited your JavaScript code, and added some missing things.
Replace all your related code with the following:
Code goes in functions.php file of your child theme (or in a plugin). It should work.