In Woocommerce checkout, I am trying to make the phone field not required for specific shipping countries. Based on "Make checkout phone field optional for specific countries in WooCommerce" answer code, which works fine, I have tried to make some changes to get this code working for the shipping country rather than billing country.
After a lot of tries, I wasn't able to figure out how to make it work.
Any help will be awesome and greatly appreciated.
The following code will make billing phone field required only for specific "Shipping" countries.
Since Woocommerce version 3.4+, things have changed a bit on Woocommerce form fields, so additional functions and code where required.
Also I have extended the code to handle the phone field behavior in My Account > Edit Addresses, where customer can make changes to his account data.
Here is the complete code (define your country codes in the first function):
// SETTINGS: The countries codes (2 capital letters) in the array
function defined_countries_for_phone_field(){
return array( 'UK', 'BE', 'GE', 'IT', 'ES' );
}
// Remove "(optional)" from non required "Billing phone" field
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address for billing phone field
if( 'billing_phone' === $key && ( ( is_wc_endpoint_url( 'edit-address' )
&& ! in_array($shipping_country, $countries) ) || is_checkout() ) ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// Make the billing phone field optional (by default)
add_filter( 'woocommerce_billing_fields', 'filter_billing_phone_field', 10, 1 );
function filter_billing_phone_field( $fields ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address
if ( ( is_wc_endpoint_url( 'edit-address' )
&& ! in_array($shipping_country, $countries) ) || is_checkout() )
$fields['billing_phone']['required'] = false;
return $fields;
}
// Real time shipping country selection actions
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_and_fields', 10, 1 );
function custom_checkout_scripts_and_fields( $checkout ) {
$required = esc_attr__( 'required', 'woocommerce' );
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Hidden field for the phone number validation
echo '<input type="hidden" name="billing_phone_check" id="billing_phone_check" value="0">';
$countries_str = "'".implode( "', '", $countries )."'"; // Formatting countries for jQuery
?>
<script type="text/javascript">
(function($){
var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>',
countries = [<?php echo $countries_str; ?>],
location = $('#shipping_country option:selected').val(),
phoneCheck = 'input#billing_phone_check',
phoneField = '#billing_phone_field';
function actionRequire( actionToDo='yes', selector='' ){
if ( actionToDo == 'yes' ) {
$(selector).addClass("validate-required");
$(selector+' label').append(required);
} else {
$(selector).removeClass("validate-required");
$(selector+' label > .required').remove();
}
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// Default value Once DOM is loaded (with a 300 ms delay)
setTimeout( function(){
actionRequire( 'no', phoneField );
if( $.inArray( location, countries ) >= 0 && $(phoneCheck).val() == '0' ){
actionRequire( 'yes',phoneField );
$(phoneCheck).val('1');
}
}, 300 );
// Live value
$( 'form.checkout' ).on( 'change', '#shipping_country', function(){
var location = $('#shipping_country option:selected').val();
if ( $.inArray( location, countries ) >= 0 && $(phoneCheck).val() == 0 ) {
actionRequire( 'yes' ,phoneField );
$(phoneCheck).val('1');
} else if ( $(phoneCheck).val() == 1 ) {
actionRequire( 'no' ,phoneField );
$(phoneCheck).val('0');
}
});
})(jQuery);
</script>
<?php
}
// Phone number validation, when the field is required
add_action('woocommerce_checkout_process', 'billing_phone_field_process');
function billing_phone_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['billing_phone'] && $_POST['billing_phone_check'] == '1' )
wc_add_notice( __( 'Please enter a number phone.' ), 'error' );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works in WooCommerce from version 3.4 and above.
Related:
Huge thanks to @LoicTheAztec for the original answer, however the solution now gives erratic results and just alternately switches the phone field between required and optional states (on / off).
The original answer also does not take into account customers who are using the billing address only and have not entered a separate delivery or shipping address.
Please see the updated version below for 2019
// SETTINGS: The countries codes (2 capital letters) in the array
function defined_countries_for_phone_field(){
return array( 'GB', 'JE', 'GG', 'IM' );
}
// Remove "(optional)" from non required "Billing phone" field
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address for billing phone field
if( 'billing_phone' === $key && ( ( is_wc_endpoint_url( 'edit-address' )
&& in_array($shipping_country, $countries) ) || is_checkout() ) ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// Make the billing phone field optional (by default)
add_filter( 'woocommerce_billing_fields', 'filter_billing_phone_field', 10, 1 );
function filter_billing_phone_field( $fields ) {
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Get Customer shipping country
$shipping_country = WC()->customer->get_shipping_country();
// Only on checkout page and My account > Edit address
if ( ( is_wc_endpoint_url( 'edit-address' )
&& in_array($shipping_country, $countries) ) || is_checkout() )
$fields['billing_phone']['required'] = false;
return $fields;
}
// Real time shipping country selection actions
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_and_fields', 10, 1 );
function custom_checkout_scripts_and_fields( $checkout ) {
$required = esc_attr__( 'required', 'woocommerce' );
// Get the defined countries codes
$countries = defined_countries_for_phone_field();
// Hidden field for the phone number validation
echo '<input type="hidden" name="billing_phone_check" id="billing_phone_check" value="0">';
$countries_str = "'".implode( "', '", $countries )."'"; // Formatting countries for jQuery
?>
<script type="text/javascript">
(function($){
var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>';
var countries = [<?php echo $countries_str; ?>];
if($('.shipping_address').is(':visible')) {
// ship to different country selected
var selectedcountry = $('#shipping_country option:selected').val();
} else {
var selectedcountry = $('#billing_country option:selected').val();
}
//var selectedcountry = $('#shipping_country option:selected').val();
var phoneCheck = 'input#billing_phone_check';
var phoneField = '#billing_phone_field';
function actionRequire( actionToDo='yes', selector='' ){
if ( actionToDo == 'yes' ) {
$(selector).addClass("validate-required");
$(selector+' label > .required').remove();
$(selector+' label').append(required);
} else {
$(selector).removeClass("validate-required");
$(selector+' label > .required').remove();
}
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// Default value Once DOM is loaded (with a 300 ms delay)
setTimeout( function(){
if($('.shipping_address').is(':visible')) {
// ship to different country selected
var selectedcountry = $('#shipping_country option:selected').val();
} else {
var selectedcountry = $('#billing_country option:selected').val();
}
actionRequire( 'no', phoneField );
if( $.inArray( selectedcountry, countries ) == -1){
actionRequire( 'yes',phoneField );
$(phoneCheck).val('1');
}
}, 300 );
// Live value
$( 'form.checkout' ).on( 'change', '#billing_country, #shipping_country, #ship-to-different-address-checkbox', function(){
setTimeout( function(){
if($('.shipping_address').is(':visible')) {
// ship to different country selected
var selectedcountry = $('#shipping_country option:selected').val();
} else {
var selectedcountry = $('#billing_country option:selected').val();
}
if ( $.inArray( selectedcountry, countries ) == -1) {
actionRequire( 'yes' ,phoneField );
$(phoneCheck).val('1');
} else {
actionRequire( 'no' ,phoneField );
$(phoneCheck).val('0');
}
}, 300 );
});
})(jQuery);
</script>
<?php
}
// Phone number validation, when the field is required
add_action('woocommerce_checkout_process', 'billing_phone_field_process');
function billing_phone_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['billing_phone'] && $_POST['billing_phone_check'] == '1' )
wc_add_notice( __( 'Please enter a number phone.' ), 'error' );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With