The existing list of countries is excellent, but we need to select Saudi Arabia in particular and show it another list with the names of the main cities such as Riyadh, Jeddah, etc. The last option is another, and if he selects another, a text box will appear to write the name of the city or region in which it is located.
I try this, Its work with me when select Saudi Arabia, i can show list of cities, but I could not do if he selects another, a text box will appear to write the name of the city or region in which it is located.
add_filter( 'woocommerce_default_address_fields' , 'customize_checkout_city_field' );
function customize_checkout_city_field( $address_fields ) {
global $woocommerce;
if ($woocommerce->customer->get_country() == 'SA') {
$towns_cities_arr = array(
'0' => __('Select City', 'my_theme_slug'),
'Abhā' => 'Abhā',
'Abqaiq' => 'Abqaiq',
'Al-Baḥah' => 'Al-Baḥah',
'Al-Dammām' => 'Al-Dammām',
'Al-Hufūf' => 'Al-Hufūf',
'Al-Jawf' => 'Al-Jawf',
'Al-Kharj' => 'Al-Kharj',
'Al-Khubar' => 'Al-Khubar',
'Al-Qaṭīf' => 'Al-Qaṭīf',
'Al-Ṭaʾif' => 'Al-Ṭaʾif',
'ʿArʿar' => 'ʿArʿar',
'Buraydah' => 'Buraydah',
'Dhahran' => 'Dhahran',
'Ḥāʾil' => 'Ḥāʾil',
'Jiddah' => 'Jiddah',
'Jīzān' => 'Jīzān',
'Khamīs Mushayt' => 'Khamīs Mushayt',
'King Khalīd Military City' => 'King Khalīd Military City',
'Mecca' => 'Mecca',
'Medina' => 'Medina',
'Najrān' => 'Najrān',
'Ras Tanura' => 'Ras Tanura',
'Riyadh' => 'Riyadh',
'Sakākā' => 'Sakākā',
'Tabūk' => 'Tabūk',
'Yanbuʿ' => 'Yanbuʿ',
'Other' => 'Other',
);
$address_fields['city']['type'] = 'select';
$address_fields['city']['class'] = array('update_totals_on_change');
$address_fields['city']['label'] = __('City', 'my_theme_slug');
$address_fields['city']['options'] = $towns_cities_arr;
} else {
$address_fields['city']['type'] = 'text';
}
return $address_fields;
}
Updated (Additional city text field when "Others" is the selected value from the dropdown)
The following code (jQuery powered) will replace the city text field by a custom dropdown of cities for a specific country only and for this specific country, if the city selected value is "Others", an additional text field will appear under the cities dropdown, where customer can enter manually a different city.
The code works for shipping and billing fields independently.
When "Others" is selected for the defined country, the two last functions will:
- Validate that the city additional field is filled,
- Save the city value as billing or shipping city value.
The code:
// HERE are is the array of cities for Saudi Arabia (SA)
function get_cities_options(){
$domain = 'woocommerce'; // The domain text slug
return array(
'' => __('Select a city', $domain),
'Abhā' => 'Abhā', 'Abqaiq' => 'Abqaiq',
'Al-Baḥah' => 'Al-Baḥah', 'Al-Dammām' => 'Al-Dammām',
'Al-Hufūf' => 'Al-Hufūf', 'Al-Jawf' => 'Al-Jawf',
'Al-Kharj' => 'Al-Kharj', 'Al-Khubar' => 'Al-Khubar',
'Al-Qaṭīf' => 'Al-Qaṭīf', 'Al-Ṭaʾif' => 'Al-Ṭaʾif',
'ʿArʿar' => 'ʿArʿar', 'Buraydah' => 'Buraydah',
'Dhahran' => 'Dhahran', 'Ḥāʾil' => 'Ḥāʾil',
'Jiddah' => 'Jiddah','Jīzān' => 'Jīzān',
'Khamīs Mushayt' => 'Khamīs Mushayt',
'King Khalīd Military City' => 'King Khalīd Military City',
'Mecca' => 'Mecca', 'Medina' => 'Medina',
'Najrān' => 'Najrān', 'Ras Tanura'=> 'Ras Tanura',
'Riyadh' => 'Riyadh', 'Sakākā' => 'Sakākā',
'Tabūk' => 'Tabūk', 'Yanbuʿ' => 'Yanbuʿ',
'Other' => __('Other cities (not listed)', $domain),
);
}
// add an additional field
add_filter( 'woocommerce_checkout_fields' , 'additional_checkout_city_field' );
function additional_checkout_city_field( $fields ) {
// Inline CSS To hide the fields on start
?><style> #billing_city2_field.hidden, #shipping_city2_field.hidden {display:none;}</style><?php
$fields['billing']['billing_city2'] = array(
'placeholder' => _x('Other city', 'placeholder', 'woocommerce'),
'required' => false,
'priority' => 75,
'class' => array('form-row-wide hidden'),
'clear' => true
);
$fields['shipping']['shipping_city2'] = array(
'placeholder' => _x('Other city', 'placeholder', 'woocommerce'),
'required' => false,
'priority' => 75,
'class' => array('form-row-wide hidden'),
'clear' => true
);
return $fields;
}
// Add checkout custom select fields
add_action( 'wp_footer', 'custom_checkout_city_field', 20, 1 );
function custom_checkout_city_field() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
$country = 'SA'; // <=== <=== The country code
$b_city = 'billing_city';
$s_city = 'shipping_city';
$billing_city_compo = 'name="'.$b_city.'" id="'.$b_city.'"';
$shipping_city_compo = 'name="'.$s_city.'" id="'.$s_city.'"';
$end_of_field = ' autocomplete="address-level2" value="">';
$billing_text_field = '<input type="text" class="input-text" ' . $billing_city_compo . $end_of_field;
$shipping_text_field = '<input type="text" class="input-text" ' . $shipping_city_compo . $end_of_field;
$billing_select_field = '<select ' . $billing_city_compo . $end_of_field;
$shipping_select_field = '<select ' . $shipping_city_compo . $end_of_field;
?>
<script type="text/javascript">
jQuery(function($){
var a = <?php echo json_encode( get_cities_options() ); ?>, fc = 'form.checkout',
b = 'billing', s = 'shipping', ci = '_city2',
bc = '<?php echo $b_city; ?>', sc = '<?php echo $s_city; ?>', co = '_country',
bci = '#'+bc, sci = '#'+sc, fi = '_field',
btf = '<?php echo $billing_text_field; ?>', stf = '<?php echo $shipping_text_field; ?>',
bsf = '<?php echo $billing_select_field; ?>', ssf = '<?php echo $shipping_select_field; ?>',
cc = '<?php echo $country; ?>';
// Utility function that fill dynamically the select field options
function dynamicSelectOptions( type ){
var select = (type == b) ? bsf : ssf,
fvalue = (type == b) ? $(bci).val() : $(sci).val();
$.each( a, function( key, value ){
selected = ( fvalue == key ) ? ' selected' : '';
selected = ( ( fvalue == '' || fvalue == undefined ) && key == '' ) ? ' selected' : selected;
select += '<option value="'+key+'"'+selected+'>'+value+'</option>';
});
select += '</select>';
if ( type == b )
$(bci).replaceWith(select);
else
$(sci).replaceWith(select);
}
// Utility function that will show / hide the "country2" additional text field
function showHideCity2( type, city ){
var field = (type == b) ? bci : sci,
country = $('#'+type+co).val();
if( country == cc && city == 'Other' && $('#'+type+ci+fi).hasClass('hidden') ){
$('#'+type+ci+fi).removeClass('hidden');
} else if( country != cc || ( city != 'Other' && ! $('#'+type+ci+fi).hasClass('hidden') ) ) {
$('#'+type+ci+fi).addClass('hidden');
if( country != cc && city == 'Other' ){
$(field).val('');
}
}
}
// On billing country change
$(fc).on('change', '#'+b+co, function(){
var bcv = $(bci).val();
if($(this).val() == cc){
if( $(bci).attr('type') == 'text' ){
dynamicSelectOptions(b);
showHideCity2( b, $(bci).val() );
}
} else {
if( $(bci).attr('type') != 'text' ){
$(bci).replaceWith(btf);
$(bci).val(bcv);
showHideCity2( b, $(bci).val() );
}
}
});
// On shipping country change
$(fc).on('change', '#'+s+co, function(){
var scv = $(sc).val();
if($(this).val() == cc){
if( $(sci).attr('type') == 'text' ){
dynamicSelectOptions(s);
showHideCity2( s, $(sci).val() );
}
} else {
if( $(sci).attr('type') != 'text' ){
$(sci).replaceWith(stf);
$(sci).val(scv);
showHideCity2( s, $(sci).val() );
}
}
});
// On billing city change
$(fc).on('change', bci, function(){
showHideCity2( b, $(this).val() );
});
// On shipping city change
$(fc).on('change', sci, function(){
showHideCity2( s, $(this).val() );
});
});
</script>
<?php
endif;
}
// Check for city 2 fields if billing or/and shipping city fields is "Other"
add_action('woocommerce_checkout_process', 'cbi_cf_process');
function cbi_cf_process() {
// Check billing city 2 field
if( isset($_POST['billing_city2']) && empty($_POST['billing_city2']) && $_POST['billing_city'] == 'Other' ){
wc_add_notice( __( "Please fill in billing city field" ), "error" );
}
// Updating shipping city 2 field
if( isset($_POST['shipping_city2']) && empty($_POST['shipping_city2']) && $_POST['shipping_city'] == 'Other' ){
wc_add_notice( __( "Please fill in shipping city field" ), "error" );
}
}
// Updating billing and shipping city fields when using "Other"
add_action( 'woocommerce_checkout_create_order', 'update_order_city_field', 30, 2 );
function update_order_city_field( $order, $posted_data ) {
// Updating billing city from 'billing_city2'
if( isset($_POST['billing_city2']) && ! empty($_POST['billing_city2']) && $_POST['billing_city'] == 'Other' ){
$order->set_billing_city(sanitize_text_field( $_POST['billing_city2'] ) );
}
// Updating shipping city
if( isset($_POST['shipping_city2']) && ! empty($_POST['shipping_city2']) && $_POST['shipping_city'] == 'Other' ){
$order->set_shipping_city(sanitize_text_field( $_POST['shipping_city'] ) );
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Please Remember that a customer can be in a foreign country outside Soudi Arabia (billing country) and buy something that will be shipped in Soudi Arabia (shipping country).