Show Hide Custom Woocommerce Checkout Field Based on Selected Payment Method

Show hide custom Woocommerce checkout field based on selected payment method

The following code will hide billing_options custom optional checkout field when the selected payment method is Cash on delivery ("cod"):

// Conditional Show hide checkout fields based on chosen payment methods
add_action( 'wp_footer', 'conditionally_show_hide_billing_custom_field' );
function conditionally_show_hide_billing_custom_field(){
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script>
jQuery(function($){
var a = 'input[name="payment_method"]',
b = a + ':checked',
c = '#billing_options_field'; // The checkout field <p> container selector

// Function that shows or hide checkout fields
function showHide( selector = '', action = 'show' ){
if( action == 'show' )
$(selector).show( 200, function(){
$(this).addClass("validate-required");
});
else
$(selector).hide( 200, function(){
$(this).removeClass("validate-required");
});
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}

// Initialising: Hide if choosen payment method is "cod"
if( $(b).val() !== 'cod' )
showHide( c, 'hide' );
else
showHide( c );

// Live event (When payment method is changed): Show or Hide based on "cod"
$( 'form.checkout' ).on( 'change', a, function() {
if( $(b).val() !== 'cod' )
showHide( c, 'hide' );
else
showHide( c );
});
});
</script>
<?php
endif;
}

Code goes in function.php file of your active child theme (or active theme). tested and works.

Show/hide custom field based on a select field with validation in WooCommerce checkout

  • If nothing is selected in the select field, an error message will appear, when submitting the form.
  • If "Referral Program" is selected, the textfield will become visible. If another option is selected, the textfield will be hidden.
  • Since the "referralname" textfield is optional, no validation is provided.

So you get:

// Add fields
function action_woocommerce_after_checkout_billing_form( $checkout ) {
// Add select field
woocommerce_form_field( 'referrence', array(
'type' => 'select', // text, textarea, select, radio, checkbox, password, about custom validation a little later
'required' => true,
'class' => array( 'my-field', 'form-row-wide' ), // array only, read more about classes and styling in the previous step
'label' => 'From where you hear about us',
'label_class' => 'my-label',
'options' => array( // options for <select> or <input type="radio" />
'' => 'Please select', // empty values means that field is not selected
'Google' => 'Google', // 'value' => 'Name'
'LinkedIn' => 'LinkedIn',
'Facebook' => 'Facebook',
'Email' => 'Email',
'Referral Program' => 'Referral Program',
'Other' => 'Other'
)
), $checkout->get_value( 'referrence' ) );

// Add textfield
woocommerce_form_field( 'referralname', array(
'type' => 'text',
'class' => array( 'my-field form-row-wide' ),
'label' => ' Referral Name',
), $checkout->get_value( 'referralname' ) );

// jQuery show/hide custom textfield
?>
<script>
jQuery(document).ready(function($) {
// Hide textfield by default
$( '#referralname_field' ).hide();

// On change
$( 'select#referrence' ).change( function() {
if ( $( 'select#referrence' ).val() == 'Referral Program' ) {
$( '#referralname_field' ).show();
} else {
$( '#referralname_field' ).hide();
}
});

});
</script>
<?php
}
add_action( 'woocommerce_after_checkout_billing_form', 'action_woocommerce_after_checkout_billing_form', 10, 1 );

// Validate select field
function action_woocommerce_checkout_process() {
// Isset
if ( isset( $_POST['referrence'] ) ) {
$domain = 'woocommerce';
$referrence = $_POST['referrence'];

// Empty
if ( empty ( $referrence ) ) {
wc_add_notice( __( 'Please select from where you hear about us', $domain ), 'error' );
}

// NOT empty but value is 'Please select'
if ( ! empty ( $referrence ) && $referrence == 'Please select' ) {
wc_add_notice( __( 'Please select from where you hear about us', $domain ), 'error' );
}
}
}
add_action( 'woocommerce_checkout_process', 'action_woocommerce_checkout_process', 10, 0 );

// Save fields
function action_woocommerce_checkout_create_order( $order, $data ) {
// Isset
if ( isset( $_POST['referrence'] ) ) {
$referrence = $_POST['referrence'];

// Update meta data
$order->update_meta_data( 'referrence', sanitize_text_field( $referrence ) );
}

// Isset
if ( isset( $_POST['referralname'] ) ) {
$referralname = $_POST['referralname'];

// Update meta data
$order->update_meta_data( 'referralname', sanitize_text_field( $referralname ) );
}
}
add_action( 'woocommerce_checkout_create_order', 'action_woocommerce_checkout_create_order', 10, 2 );

Conditionally hide Woocommerce checkout custom field based on free shipping

As it's a live event, you need to use javascript/jQuery to make it work. Your "billing_field_432" has to be not required, because when field is hidden and trying to submit the order, will throw an error notice message for this custom checkout field.

The code to show / hide that field based on 'free_shipping:5' Shipping method:

// Conditional Show hide checkout fields based on chosen shipping methods
add_action( 'wp_footer', 'conditionally_hidding_billing_custom_field' );
function conditionally_hidding_billing_custom_field(){
// Only on checkout page
if( ! is_checkout() ) return;

// HERE your shipping methods rate ID "Free shipping"
$free_shipping = 'free_shipping:5';
?>
<script>
jQuery(function($){
// Choosen shipping method selectors slug
var sm = 'input[name^="shipping_method"]',
smc = sm + ':checked',
cbf = '#billing_field_432_field',
ihc = 'input[name="hidden_check"]';

// Function that shows or hide imput select fields
function showHide( selector = '', action = 'show' ){
if( action == 'show' )
$(selector).show( 200, function(){
$(this).addClass("validate-required");
$(ihc).val('1'); // Set hidden field for checkout process
});
else
$(selector).hide( 200, function(){
$(this).removeClass("validate-required");
$(ihc).val(''); // Set hidden field for checkout process
});
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}

// Initialising: Hide if choosen shipping method is "Free Shipping" method
if( $(smc).val() == '<?php echo $free_shipping; ?>' )
showHide( cbf, 'hide' );
else
$(ihc).val('1'); // Set hidden field for checkout process

// Live event (When shipping method is changed): Show or Hide based on "Free Shipping" method
$( 'form.checkout' ).on( 'change', sm, function() {
if( $(smc).val() == '<?php echo $free_shipping; ?>' )
showHide( cbf, 'hide' );
else
showHide( cbf );
});
});
</script>
<?php
}

The code to add a custom checkout hidden input field to enable the "required" field option check process when 'billing_field_432' is not hidden:

// Add a hidden input field for "required" option check process
add_filter('woocommerce_checkout_fields', 'add_custom_hidden_input_field' );
function add_custom_hidden_input_field( $fields ) {

echo '<input type="hidden" id="hidden_check" name="hidden_check" value="">';

return $fields;
}

// Check custom checkout field "billing_field_432" when not hidden
add_action('woocommerce_checkout_process', 'check_custom_field_checkout_process');
function check_custom_field_checkout_process() {
// Check if set, if its not set add an error.
if ( isset( $_POST['hidden_check'] ) && $_POST['hidden_check'] && empty( $_POST['billing_field_432'] ) )
wc_add_notice( __( 'Please enter something in "billing field 432".' ), 'error' ); // SET your custom error notice
}

This code goes on function.php file of your active child theme (or theme). Tested and works.

It's based on: Conditionally hide a Checkout field in WooCommerce based on chosen shipping


As you are using free shipping method with a minimum order amount of "50" and hiding other shipping methods when "free shipping" is available. You should use this instead:

// Unset checkout field based on cart amount for free shipping
add_filter('woocommerce_checkout_fields', 'remove_checkout_billing_field_432', 999 );
function remove_checkout_billing_field_432( $fields ) {
if ( WC()->cart->cart_contents_total >= 50 ) {
unset($fields['billing']['billing_field_432']); // Unset field
}
return $fields;
}

This code goes on function.php file of your active child theme (or theme). Tested and works.

Show hide payment gateways based on checkout fields in Woocommerce

The following code will hide all payment gateways except "Cash on delivery" (COD) when "Ship to a different address?" is checked (and the shipping checkout fields are shown):

// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_billing_area_script' );
function checkout_billing_area_script() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):

// Remove "ship_different" custom WC session on load
if( WC()->session->get('ship_different') ){
WC()->session->__unset('ship_different');
}
// jQuery Ajax code below
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;

var a = '#ship-to-different-address-checkbox', b = '';

// Ajax function
function triggerSTDA( value ){
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'ship_different_address',
'ship_different': value,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log(result); // For testing (to be removed)
}
});
}

$(a).on( 'change', function(){
b = $(this).prop('checked') === true ? 'yes' : 'no';
triggerSTDA( b );
});
});
</script>
<?php
endif;
}

// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_ship_different_address', 'get_ajax_ship_different_address' );
add_action( 'wp_ajax_nopriv_ship_different_address', 'get_ajax_ship_different_address' );
function get_ajax_ship_different_address() {
if ( isset($_POST['ship_different']) ){
WC()->session->set('ship_different', esc_attr($_POST['ship_different']));
echo $_POST['ship_different'];
}
die();
}

// Show/hide payment gateways
add_filter( 'woocommerce_available_payment_gateways', 'conditionally_hide_payment_gateways', 100, 1 );
function conditionally_hide_payment_gateways( $available_gateways ) {
if( WC()->session->get('ship_different') == 'yes' ) {
foreach( $available_gateways as $gateways_id => $gateways ){
if( $gateways_id !== 'cod' ) {
unset($available_gateways[$gateways_id]);
}
}
}
return $available_gateways;
}

Code goes in function.php file of your active child theme (or active theme). Tested and work.

Show or hide checkout postcode field based on chosen city in WooCommerce

It's a bit much more complicated and you will need to define the city in the last function.

The following code handles multiple necessary tasks to show / hide the postcode field based on a specific defined selected city:

// Make postcode field optional
add_filter( 'woocommerce_default_address_fields', 'customizing_checkout_fields' );
function customizing_checkout_fields( $fields ) {
if( is_checkout() ) {
$fields['postcode']['required'] = false;
}
return $fields;
}

// Replace "(optional)" text by required "*"
add_filter( 'woocommerce_form_field' , 'replace_checkout_optional_by_required', 10, 4 );
function replace_checkout_optional_by_required( $field, $key, $args, $value ) {
// Only on checkout page for postcode field
if( is_checkout() && ! is_wc_endpoint_url() && in_array($key, ['billing_postcode', 'shipping_postcode']) ) {
$optional = '<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$required = '<abbr class="required" title="required">*</abbr>';
$field = str_replace( $optional, $required, $field );
}
return $field;
}

// Hidden input fields for Postcode validation when it's visible
add_action( 'woocommerce_after_order_notes', 'checkout_hidden_field_for_validation', 10, 1 );
function checkout_hidden_field_for_validation( $checkout ) {
// Hidden field for the phone number validation
echo '<input type="hidden" name="billing_postcode_check" id="billing_postcode_check" value="">
<input type="hidden" name="shipping_postcode_check" id="shipping_postcode_check" value="">';
}

// Postcode field validation when it's visible
add_action('woocommerce_checkout_process', 'wps_select_checkout_field_process');
function wps_select_checkout_field_process() {
if( isset($_POST['billing_postcode_check']) && $_POST['billing_postcode_check'] === 'yes'
&& isset($_POST['billing_postcode']) && empty($_POST['billing_postcode']) ) {
wc_add_notice( __("The billing postcode field is a required field.", "woocommerce"), 'error' );
}

if( isset($_POST['shipping_postcode_check']) && $_POST['shipping_postcode_check'] === 'yes'
&& isset($_POST['shipping_postcode']) && empty($_POST['shipping_postcode']) ) {
wc_add_notice( __("The shipping postcode is a required field.", "woocommerce"), 'error' );
}
}

// Conditional Show hide checkout fields based on chosen payment methods
add_action( 'wp_footer', 'conditionally_show_hide_billing_custom_field' );
function conditionally_show_hide_billing_custom_field(){
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() ) :

// HERE define the city that will hide postcode field
$city = 'Paris';

$required = ' <abbr class="required" title="required">*</abbr>';
?>
<script>
jQuery(function($){
var bc = '#billing_city_field input',
sc = '#shipping_city_field input',
bp = '#billing_postcode_field',
sp = '#shipping_postcode_field',
bpc = '#billing_postcode_check',
spc = '#shipping_postcode_check',
city = '<?php echo $city; ?>',
req = '<?php echo $required; ?>';

// On "update" checkout form event, replace "(optional)" by required "*"
$(document.body).on('update_checkout', function(){
$('#billing_postcode_field label > .optional').replaceWith(req);
});

// Function that shows or hide checkout fields
function showHide( selector = '', action = 'show' ){
var check = selector == bp ? $(bpc) : $(spc);
if( action == 'show' )
$(selector).show( 200, function(){
$(this).addClass("validate-required");
check.val('yes');
});
else
$(selector).hide( 200, function(){
$(this).removeClass("validate-required");
check.val('');
});
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}

// 1. Initialising (on load): Show/hide based on customer city

// Billing field
if( $(bc).val() === city || $(bc).val() == '' )
showHide( bp, 'hide' );
else
showHide( bp );

// Shipping field
if( $(sc).val() === city || $(sc).val() == '' )
showHide( sp, 'hide' );
else
showHide( sp );

// 2. Change live event: Show/hide based on city change

$( 'form.checkout' ).on( 'change input', bc, function() { // Billing field
if( $(bc).val() === city )
showHide( bp, 'hide' );
else
showHide( bp );
});

$( 'form.checkout' ).on( 'change input', sc, function() { // Shipping field
if( $(sc).val() === city )
showHide( sp, 'hide' );
else
showHide( sp );
});
});
</script>
<?php
endif;
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Some related answers:

  • Show hide custom Woocommerce checkout field based on selected payment method
  • Remove "(optional)" text from checkout fields in Woocommerce 3.4+

Hidding billing and shipping postcode on load:

Replace:

            // 1. Initialising (on load): Show/hide based on customer city

// Billing field
if( $(bc).val() === city || $(bc).val() == '' )
showHide( bp, 'hide' );
else
showHide( bp );

// Shipping field
if( $(sc).val() === city || $(sc).val() == '' )
showHide( sp, 'hide' );
else
showHide( sp );

by:

            // 1. Initialising (on load): Hide postcode

showHide( bp, 'hide' ); // Billing field
showHide( sp, 'hide' ); // Shipping field

Hide checkout fields when selecting multiple delivery methods in WooCommerce

The above code does not make fileds not required. Only solution I've found to work around is fill up hidden fields with placeholder value.

// Conditional Show hide checkout fields based on chosen shipping methods
add_action( 'wp_footer', 'custom_checkout_field_script' );
function custom_checkout_field_script() {

// HERE your shipping methods rate IDs
$local_pickup = array('inpost_paczkomaty:15');
$required_text = esc_attr__( 'required', 'woocommerce' );
$required_html = '<abbr class="required" title="' . $required_text . '">*</abbr>';
?>
<script>
jQuery(function($){
var ism = 'input[name^="shipping_method"]',
ismc = ism+':checked',
csa = 'input#ship-to-different-address-checkbox',
rq = '-required',
vr = 'validate'+rq,
w = 'woocommerce',
wv = w+'-validated',
iv = '-invalid',
fi = '-field',
wir = w+iv+' '+w+iv+rq+fi,
b = '#billing_',
s = '#shipping_',
f = '_field',
a1 = 'country', a2 = 'address_1', a3 = 'address_2', a4 = 'postcode', a5 = 'state', a6 = 'city',
b1 = b+a1+f, b2 = b+a2+f, b3 = b+a3+f, b4 = b+a4+f, b5 = b+a5+f, b6 = b+a6+f,
s1 = s+a1+f, s2 = s+a2+f, s3 = s+a3+f, s4 = s+a4+f, s5 = s+a5+f, s6 = s+a6+f,
localPickup = '<?php echo json_encode($local_pickup); ?>';

// Utility function to shows or hide checkout fields
function showHide( action='show', selector='' ){
if( action == 'show' ){
$(selector).show(function(){
$(this).addClass(vr);
$(this).removeClass(wv);
$(this).removeClass(wir);
if( $(selector+' > label > abbr').html() == undefined )
$(selector+' label').append('<?php echo $required_html; ?>');
});
} else {
$(selector).hide(function(){
$(this).removeClass(vr);
$(this).removeClass(wv);
$(this).removeClass(wir);
$(this).find("[type='text']").val('00-000');
if( $(selector+' > label > abbr').html() != undefined ){
$(selector+' label > .required').remove();
}
});
}
}

// Initializing at start after checkout init (Based on the chosen shipping method)
setTimeout(function(){
if( localPickup.includes( $(ismc).val() ) ){ // Choosen "Local pickup" (Hidding "Take away")
showHide('hide',b1); //Country
showHide('hide',b2); //Address line 1
showHide('hide',b3); //Address line 2
showHide('hide',b4); //Postcode
showHide('hide',b5); //State
showHide('hide',b6); //City
}else{
showHide('hide',b1); //Country
showHide('show',b2); //Address line 1
showHide('hide',b3); //Address line 2
showHide('show',b4); //Postcode
showHide('hide',b5); //State
showHide('show',b6); //City
}
}, 100);

// When shipping method is changed (Live event)
$( 'form.checkout' ).on( 'change', ism, function() {
if( localPickup.includes( $(ismc).val() ) ){
showHide('hide',b1); //Country
showHide('hide',b2); //Address line 1
showHide('hide',b3); //Address line 2
showHide('hide',b4); //Postcode
showHide('hide',b5); //State
showHide('hide',b6); //City

if( $(csa).prop('checked') ) {
showHide('hide',s1);
showHide('hide',s2);
showHide('hide',s3);
showHide('hide',s4);
showHide('hide',s5);
showHide('hide',s6);
}
}else{
showHide('hide',b1); //Country
showHide('show',b2); //Address line 1
showHide('hide',b3); //Address line 2
showHide('show',b4); //Postcode
showHide('hide',b5); //State
showHide('show',b6); //City

if( $(csa).prop('checked') ) {
showHide('hide',s1);
showHide('hide',s2);
showHide('hide',s3);
showHide('hide',s4);
showHide('hide',s5);
showHide('hide',s6);
}
}
});

// When "shipping to different address" is changed (Live event)
$(csa).click( function() {
if( localPickup.includes( $(ismc).val() ) && $(this).prop('checked') ){
showHide('hide',b1);
showHide('hide',b2);
showHide('hide',b3);
showHide('hide',b4);
showHide('hide',b4);
showHide('hide',b6);

showHide('hide',s1);
showHide('hide',s2);
showHide('hide',s3);
showHide('hide',s4);
showHide('hide',s5);
showHide('hide',s6);
}else{
showHide('hide',b1);
showHide('hide',b2);
showHide('hide',b3);
showHide('hide',b4);
showHide('hide',b4);
showHide('hide',b6);

showHide('hide',s1);
showHide('show',s2);
showHide('hide',s3);
showHide('show',s4);
showHide('hide',s5);
showHide('show',s6);
}
});
});
</script>
<?php
}

WooCommerce: Show or hide checkout fields and sections based on chosen shipping method

You just need some small changes in your jQuery code (removed some useless code):

<script>
jQuery( function($) {
function toggleFieldsClasses( value ) {
// change local_pickup:4 accordingly
$('.billing-dynamic_pickup').toggleClass('hide_pickup', value == 'local_pickup:2');
$('.woocommerce-shipping-fields').toggleClass('hide_shipping', value == 'local_pickup:2');
$('#coderockz_woo_delivery_delivery_date_section').toggleClass('hide_delivery_date_field', value == 'local_pickup:2');
$('#coderockz_woo_delivery_delivery_time_section').toggleClass('hide_delivery_time_field', value == 'local_pickup:2');
$('#coderockz_woo_delivery_pickup_date_section').toggleClass('hide_pickup_date_field', value == 'flat_rate:1' || value == 'free_shipping:3');
$('#coderockz_woo_delivery_pickup_time_section').toggleClass('hide_pickup_time_field', value == 'flat_rate:1' || value == 'free_shipping:3');
}

// Once DOM is loaded
toggleFieldsClasses( $('#shipping_method input[type="radio"]:checked').val() );

// On change
$( document.body ).on( 'change', '#shipping_method input[type="radio"]', function() {
toggleFieldsClasses( this.value );
});
});
</script>

Untested, it should work now as expected when coming from cart to checkout page.



Related Topics



Leave a reply



Submit