skip to Main Content

I want to make a WooCommerce Checkout Field that only shows up when a specific payment (Cash On Delivery) is chosen. This field should only show up and only be required when cash on delivery is chosen. I have managed to make the field and have it show up conditionally, but I cannot figure out how to make it required only when COD is chosen.

/* Only show EAN when COD chosen */

// 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;
}

/* Add extra field and make it required */

add_filter('woocommerce_billing_fields', 'custom_woocommerce_billing_fields');

function custom_woocommerce_billing_fields($fields)
{

    $fields['billing_options'] = array(
        'label' => __('– EAN-nummer – ', 'woocommerce'), // Add custom field label
        'placeholder' => _x('EAN nummer', 'placeholder', 'woocommerce'), // Add custom field placeholder
        'required' => true, // if field is required or not
        'clear' => false, // add clear or not
        'type' => 'text', // add field type
        'class' => array('my-css')    // add class name
    );

    return $fields;
}

2

Answers


  1. add_action('woocommerce_after_checkout_validation', 'woocommerce_after_checkout_validation_alter', 10, 2);
    
    function woocommerce_after_checkout_validation_alter($data, $errors){
    
        if('cod' !== $data['payment_method']){
            if($errors->get_error_data('billing_options_required')){ // This will contain the error
                $errors->remove('billing_options_required');
            }
        }
        return $data;
    }
    

    Remove the validation error from the error object if the payment method selected is not COD. The error object will be like the below.

    WP_Error Object
    (
        [errors] => Array
            (
                [billing_options_required] => Array
                    (
                        [0] => <strong>Billing – EAN-nummer – </strong> is a required field.
                    )
    
            )
    
        [error_data] => Array
            (
                [billing_options_required] => Array
                    (
                        [id] => billing_options
                    )
    
            )
    
        [additional_data:protected] => Array
            (
            )
    
    )
    
    Login or Signup to reply.
  2. It’s not advised to parse out the woocomerce error post-validation, it’s a much better idea to Handle The Validation Correctly In the First Place

    To conditionally set a field as required at the checkout it’s much better to use the woocommerce_checkout_fields hook, so we can make any changes prior to the form being processed, this function allows you to programmatically access and set the values of each checkout field, and can be copy/pasted into your functions.php file to achieve what you are looking for.

    /**
     * Skip Validation for EAN field when COD is not chosen
     *
     * @param array $fields
     * @return array
     */
    function woocommerce_no_ean( array $fields ): array {
        // bail if the payment method is not COD
        if ( ! isset( $_POST['payment_method'] ) || 'cod' === $_POST['payment_method'] ) {
            return $fields;
        }
        $fields['billing']['billing_options']['required'] = false;
        return $fields;
    } add_filter( 'woocommerce_checkout_fields', 'woocommerce_no_ean' );
    

    Additionally here are a few other tips:

    It’s always a good idea to validate any form data, especially checkout data to ensure it’s valid, after a quick google, if by EAN number you are referring to This I have made an additional function for you to validate that the field is 13 numbers long, if you would like to use it just place it in your functions file as well

    /**
     * Validate the EAN field on checkout submission
     *
     * This is a simple example of how to validate a custom field on checkout submission,
     * for the EAN field we are checking if the value is numeric and if it's 13 digits long.
     *
     * To remove the validation, simply remove the add_action() function and everything after it.
     *
     * @return void
     * @see https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
     */
    function woocomerce_validate_ean(): void {
        // validate the woocommerce nonce
        if ( ! isset( $_POST['woocommerce-process-checkout-nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce-process-checkout-nonce'], 'woocommerce-process_checkout' ) ) {
            wc_add_notice( __( 'Checkout Validation Error, Please Try Refreshing The Page' ), 'error' );
            return;
        }
        // bail if the payment method is not COD
        if ( ! isset( $_POST['payment_method'] ) || 'cod' !== $_POST['payment_method'] ) {
            return;
        }
        if ( ! isset( $_POST['billing_options'] ) || empty( $_POST['billing_options'] ) ||
            ! is_numeric( $_POST['billing_options'] )
            || ! preg_match( '/^[0-9]{13}$/', $_POST['billing_options'] ) ) {
            wc_add_notice( ( 'Please enter a valid EAN number.' ), 'error' );
            wc_add_notice( ( 'EAN number must be 13 digits.' ), 'notice' );
        }
    } add_action( 'woocommerce_checkout_process', 'woocomerce_validate_ean' );
    

    It’s also a good idea not to put too much javascript into your php files, so I would recommend using the wp_enqueue_scripts hook to conditionally load your javascript files as-needed

    you can replace the entire wp-footer block with this

    /**
     * enqueue custom ean javascript
     *
     * This is assuming that you have a file located at {theme_root}/assets/js/eancheckout.js
     */
    function enqueue_ean_checkout_js() {
        if ( is_checkout() ) {
            wp_enqueue_script( 'ean-checkout-js', get_stylesheet_directory_uri() . '/assets/js/eancheckout.js', array( 'jquery' ), '1.0', true );
        }
    } add_action( 'wp_enqueue_scripts', 'enqueue_ean_checkout_js' );
    

    and create a file called eancheckout.js in your theme/assets/js folder, such as

    // Conditional Show hide checkout fields based on chosen payment methods
    (($) => {
        'use strict';
            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);
            });
    })(jQuery);
    

    So if you would like to impliment all of these, just make that js file and this is the complete functions.php file result for this

    
    
    /**
     * enqueue custom ean javascript
     *
     * This is assuming that you have a file located at {theme_root}/assets/js/eancheckout.js
     */
    function enqueue_ean_checkout_js() {
        if ( is_checkout() ) {
            wp_enqueue_script( 'ean-checkout-js', get_stylesheet_directory_uri() . '/assets/js/eancheckout.js', array( 'jquery' ), '1.0', true );
        }
    } add_action( 'wp_enqueue_scripts', 'enqueue_ean_checkout_js' );
    
    /* Add extra field and make it required */
    function custom_woocommerce_billing_fields( $fields ) {
    
        $fields['billing_options'] = array(
            'label'       => __( 'EAN-nummer', 'woocommerce' ), // Add custom field label
            'placeholder' => _x( 'EAN nummer', 'placeholder', 'woocommerce' ), // Add custom field placeholder
            'required'    => true, // if field is required or not
            'clear'       => false, // add clear or not
            'type'        => 'text', // add field type
            'class'       => array( 'my-css' ),    // add class name
        );
    
        return $fields;
    } add_filter( 'woocommerce_billing_fields', 'custom_woocommerce_billing_fields' );
    
    
    /**
     * Skip Validation for EAN field when COD is not chosen
     *
     * @param array $fields
     * @return array
     */
    function woocommerce_no_ean( array $fields ): array {
        // bail if the payment method is not COD
        if ( ! isset( $_POST['payment_method'] ) || 'cod' === $_POST['payment_method'] ) {
            return $fields;
        }
        $fields['billing']['billing_options']['required'] = false;
        return $fields;
    } add_filter( 'woocommerce_checkout_fields', 'woocommerce_no_ean' );
    
    
    /**
     * Validate the EAN field on checkout submission
     *
     * This is a simple example of how to validate a custom field on checkout submission,
     * for the EAN field we are checking if the value is numeric and if it's 13 digits long.
     *
     * To remove the validation, simply remove the add_action() function and everything after it.
     *
     * @return void
     * @see https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
     */
    function woocomerce_validate_ean(): void {
        // validate the woocommerce nonce
        if ( ! isset( $_POST['woocommerce-process-checkout-nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce-process-checkout-nonce'], 'woocommerce-process_checkout' ) ) {
            wc_add_notice( __( 'Checkout Validation Error, Please Try Refreshing The Page' ), 'error' );
            return;
        }
        // bail if the payment method is not COD
        if ( ! isset( $_POST['payment_method'] ) || 'cod' !== $_POST['payment_method'] ) {
            return;
        }
        if ( ! isset( $_POST['billing_options'] ) || empty( $_POST['billing_options'] ) ||
            ! is_numeric( $_POST['billing_options'] )
            || ! preg_match( '/^[0-9]{13}$/', $_POST['billing_options'] ) ) {
            wc_add_notice( ( 'Please enter a valid EAN number.' ), 'error' );
            wc_add_notice( ( 'EAN number must be 13 digits.' ), 'notice' );
        }
    } add_action( 'woocommerce_checkout_process', 'woocomerce_validate_ean' );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search