Bursuc Andrei Bursuc Andrei - 1 month ago 10
jQuery Question

Displaying custom checkout fields based on a selector choice

Based on this working answer:

Custom dropdown selector showing or hiding other Checkout custom fields

In WooCommerce checkout page I use the code below to create some additional custom fields and reorder all the checkout fields. I use a jQuery script to show/hide some fields based on a selector choice.

Here is my new code:

// Registering external jQuery/JS file
function cfields_scripts() {

/* IMPORTANT NOTE: For a child theme replace get_template_directory_uri() by get_stylesheet_directory_uri()
The external cfields.js file goes in a subfolder "js" of your active child theme or theme.*/

wp_enqueue_script( 'checkout_script', get_template_directory_uri().'/js/cfields.js', array('jquery'), '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'cfields_scripts' );


add_filter( 'woocommerce_checkout_fields', 'custom_checkout_billing_fields' );
function custom_checkout_billing_fields( $fields ) {

// 1. Creating the additional custom billing fields

// The "status" selector
$fields['billing']['billing_status']['type'] = 'select';
$fields['billing']['billing_status']['class'] = array('form-row-wide, status-select');
$fields['billing']['billing_status']['required'] = true;
$fields['billing']['billing_status']['label'] = __('Statut Juridic', 'my_theme_slug');
$fields['billing']['billing_status']['placeholder'] = __('Alege statutul', 'my_theme_slug');
$fields['billing']['billing_status']['options'] = array(
'1' => __( 'Persoana Fizica', '' ),
'2' => __( 'Persoana Juridica', '' )
);

// Customizing 'billing_company' field ['required']
$fields['billing']['billing_company']['required'] = false;
$fields['billing']['billing_company']['class'] = array('form-row-wide', 'status-group2');

// The "Nr. registrul comertului" text field
$fields['billing']['billing_ser_id']['type'] = 'text';
$fields['billing']['billing_ser_id']['class'] = array('form-row-wide', 'status-group2');
$fields['billing']['billing_ser_id']['required'] = false;
$fields['billing']['billing_ser_id']['label'] = __('Nr. Reg. Comert', 'my_theme_slug');
$fields['billing']['billing_ser_id']['placeholder'] = __('Introdu numarul', 'my_theme_slug');

// The "Banca" text field
$fields['billing']['billing_bt_id']['type'] = 'text';
$fields['billing']['billing_bt_id']['class'] = array('form-row-wide', 'status-group2');
$fields['billing']['billing_bt_id']['required'] = false;
$fields['billing']['billing_bt_id']['label'] = __('Banca', 'my_theme_slug');
$fields['billing']['billing_bt_id']['placeholder'] = __('Adauga Banca', 'my_theme_slug');

// The "IBAN" text field
$fields['billing']['billing_ib_id']['type'] = 'text';
$fields['billing']['billing_ib_id']['class'] = array('form-row-wide', 'status-group2');
$fields['billing']['billing_ib_id']['required'] = false;
$fields['billing']['billing_ib_id']['label'] = __('IBAN', 'my_theme_slug');
$fields['billing']['billing_ib_id']['placeholder'] = __('Adauga IBAN-ul', 'my_theme_slug');

// The "CIF" text field
$fields['billing']['billing_cf_id']['type'] = 'text';
$fields['billing']['billing_cf_id']['class'] = array('form-row-wide', 'status-group2');
$fields['billing']['billing_cf_id']['required'] = false;
$fields['billing']['billing_cf_id']['label'] = __('Cod Fiscal', 'my_theme_slug');
$fields['billing']['billing_cf_id']['placeholder'] = __('Adauga CIF-ul', 'my_theme_slug');


// 3. Ordering the billing fields

$fields_order = array(
'billing_first_name', 'billing_last_name', 'billing_email',
'billing_phone', 'billing_address_1', 'billing_address_2',
'billing_postcode', 'billing_city', 'billing_country',
'billing_status',
'billing_company', 'billing_ser_id', 'billing_bt_id',
'billing_ib_id', 'billing_cf_id'
);
foreach($fields_order as $field) $ordered_fields[$field] = $fields['billing'][$field];

$fields['billing'] = $ordered_fields;


// Returning Checkout customized billing fields

return $fields;

}


// Process the checkout
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['billing_ser_id'] )
wc_add_notice( __( 'Please enter your Serial id.' , 'my_theme_slug' ), 'error' );
if ( ! $_POST['billing_bt_id'] )
wc_add_notice( __( 'Please enter your Serial id.' , 'my_theme_slug' ), 'error' );
if ( ! $_POST['billing_ib_id'] )
wc_add_notice( __( 'Please enter your Serial id.' , 'my_theme_slug' ), 'error' );
if ( ! $_POST['billing_cf_id'] )
wc_add_notice( __( 'Please enter your Serial id.' , 'my_theme_slug' ), 'error' );
}

// Update the order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'custom_checkout_field_update_order_meta' );
function custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['billing_ser_id'] ) )
update_post_meta( $order_id, 'billing_ser_id', sanitize_text_field( $_POST['billing_ser_id'] ) );
if ( ! empty( $_POST['billing_bt_id'] ) )
update_post_meta( $order_id, 'billing_bt_id', sanitize_text_field( $_POST['billing_bt_id'] ) );
if ( ! empty( $_POST['billing_ib_id'] ) )
update_post_meta( $order_id, 'billing_ib_id', sanitize_text_field( $_POST['billing_ib_id'] ) );
if ( ! empty( $_POST['billing_cf_id'] ) )
update_post_meta( $order_id, 'billing_cf_id', sanitize_text_field( $_POST['billing_cf_id'] ) );
}


// Display field value on the order edit page
add_action( 'woocommerce_admin_order_data_after_billing_address', 'custom_checkout_field_display_admin_order_meta', 10, 1 );
function custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('My serial identification').':</strong> ' . get_post_meta( $order->id, 'billing_ser_id', true ) . '</p>';
echo '<p><strong>'.__('My serial identification').':</strong> ' . get_post_meta( $order->id, 'billing_bt_id', true ) . '</p>';
echo '<p><strong>'.__('My serial identification').':</strong> ' . get_post_meta( $order->id, 'billing_ib_id', true ) . '</p>';
echo '<p><strong>'.__('My serial identification').':</strong> ' . get_post_meta( $order->id, 'billing_cf_id', true ) . '</p>';
}


Javascript
cfields.js
code
(incomplete external file):

// This file named "cfields.js" goes in a subfolder "js" of your active child theme or theme

jQuery(document).ready(function($){

$('#billing_company_field').hide(function(){
$(this).removeClass("validate-required");
});
$('#billing_ser_id_field').hide(function(){
$(this).removeClass("validate-required");
});
$("#billing_number_id_field").addClass("validate-required");

$("#billing_status").change(function(){
if($("#billing_status option:selected").val() == "2"){
$('#billing_company_field').show(function(){
$(this).addClass("validate-required");
});
$('#billing_ser_id_field').show(function(){
$(this).addClass("validate-required");
});
} else if($("#billing_status option:selected").val() == "1"){
$('#billing_company_field').hide(function(){
$(this).removeClass("validate-required");
});
$('#billing_ser_id_field').hide(function(){
$(this).removeClass("validate-required");
});
}

});

});


As I have some additional fields and what I need now is when the
billing_status
selector is on:


  1. Persoana Fizica option value (Individual): showing only
    billing_serial
    custom field.

  2. Persoana Juridica option value (Company), 4 more fields will appear:


    • billing_company
      existing field (at first, before
      billing_serial
      )

    • billing_registration_id
      custom field (this field is always shown, in both cases)

    • billing_bank_id
      custom field

    • billing_bankno_id
      custom field

    • billing_cif_id
      custom field




Also I would like to display this data on Thankyou Oder receive page and on email notifications.

I haven't find the way to get it working. How can I make it work properly?

Thanks in advance.

Answer Source

UPDATE HERE FOR REORDERING CHECKOUT FIELDS IN WC 3+

As you have add others customs fields and make some changes, you will find below the necessary code to make it work properly. This is becoming a real development and shouldn't be asked in here. I try to always finish what I have began, so I answer it.

The most difficult thing here is to avoid WooCommerce alert notice on hidden required fields when selector is on Individual. For this you are obliged (with the help of jQuery) to imput a "no" value in that hidden fields.

So when the order will be submitted, you will get all the custom fields values in the order meta data (for Individual your hidden fields will have a "no" value. It's the only possible way.
But as we can process the displayed data and even update it afterwards, this is not a problem, as you will seeā€¦

Here is the PHP code (which goes in function.php):

 // Registering external jQuery/JS file
function cfields_scripts() {

    // IMPORTANT NOTE:
    // For a child theme replace get_template_directory_uri() by get_stylesheet_directory_uri()
    // The external cfields.js file goes in a subfolder "js" of your active child theme or theme.
    wp_enqueue_script( 'checkout_script', get_template_directory_uri().'/js/cfields.js', array('jquery'), '1.0', true );

}
add_action( 'wp_enqueue_scripts', 'cfields_scripts' );


add_filter( 'woocommerce_checkout_fields', 'ba_custom_checkout_billing_fields' );
function ba_custom_checkout_billing_fields( $fields ) {

    // 1. Creating the additional custom billing fields

    // The "status" selector
    $fields['billing']['billing_status']['type'] = 'select';
    $fields['billing']['billing_status']['class'] = array('form-row-wide, status-select');
    $fields['billing']['billing_status']['required'] = true;
    $fields['billing']['billing_status']['label'] = __('Statut Juridic', 'theme_domain');
    $fields['billing']['billing_status']['placeholder'] = __('Alege statutul', 'theme_domain');
    $fields['billing']['billing_status']['options'] = array(
        '1' => __( 'Persoana Fizica', 'theme_domain' ),
        '2' => __( 'Persoana Juridica', 'theme_domain' )
    );

    // The "Nr. registrul comertului" text field (this field is common)
    $fields['billing']['billing_ser_id']['type'] = 'text';
    $fields['billing']['billing_ser_id']['class'] = array('form-row-wide', 'status-group2');
    $fields['billing']['billing_ser_id']['required'] = true; // <== HERE has to be "true" as it always be shown and need validation
    $fields['billing']['billing_ser_id']['label'] = __('Nr. Reg. Comert', 'theme_domain');
    $fields['billing']['billing_ser_id']['placeholder'] = __('Introdu numarul', 'theme_domain');

    // The "Banca" text field
    $fields['billing']['billing_bt_id']['type'] = 'text';
    $fields['billing']['billing_bt_id']['class'] = array('form-row-wide', 'status-group2');
    $fields['billing']['billing_bt_id']['required'] = false;
    $fields['billing']['billing_bt_id']['label'] = __('Banca', 'theme_domain');
    $fields['billing']['billing_bt_id']['placeholder'] = __('Adauga Banca', 'theme_domain');

    // The "IBAN" text field
    $fields['billing']['billing_ib_id']['type'] = 'text';
    $fields['billing']['billing_ib_id']['class'] = array('form-row-wide', 'status-group2');
    $fields['billing']['billing_ib_id']['required'] = false;
    $fields['billing']['billing_ib_id']['label'] = __('IBAN', 'theme_domain');
    $fields['billing']['billing_ib_id']['placeholder'] = __('Adauga IBAN-ul', 'theme_domain');

    // The "CIF" text field
    $fields['billing']['billing_cf_id']['type'] = 'text';
    $fields['billing']['billing_cf_id']['class'] = array('form-row-wide', 'status-group2');
    $fields['billing']['billing_cf_id']['required'] = false;
    $fields['billing']['billing_cf_id']['label'] = __('Cod Fiscal', 'theme_domain');
    $fields['billing']['billing_cf_id']['placeholder'] = __('Adauga CIF-ul', 'theme_domain');


    // 2. Ordering the billing fields

    $fields_order = array(
        'billing_first_name', 'billing_last_name', 'billing_email',
        'billing_phone',      'billing_address_1', 'billing_address_2',
        'billing_postcode',   'billing_city',      'billing_country',
        'billing_status',     'billing_company',   'billing_ser_id',
        'billing_bt_id',      'billing_ib_id',     'billing_cf_id'
    );

    foreach($fields_order as $field)
        $ordered_fields[$field] = $fields['billing'][$field];

    $fields['billing'] = $ordered_fields;


    // 4. Returning Checkout customized billing fields
    return $fields;

}


// Process the checkout (Checking if required fields are not empty)
add_action('woocommerce_checkout_process', 'ba_custom_checkout_field_process');
function ba_custom_checkout_field_process() {

    if ( ! $_POST['billing_ser_id'] )
        wc_add_notice( __( '<strong>Nr. Reg. Comert</strong> is a required field.', 'theme_domain' ), 'error' );

    if ( ! $_POST['billing_bt_id'] )
        wc_add_notice( __( '<strong>Banca</strong> is a required field.', 'theme_domain' ), 'error' );

    if ( ! $_POST['billing_ib_id'] )
        wc_add_notice( __( '<strong>IBAN</strong> is a required field.', 'theme_domain' ), 'error' );

    if ( ! $_POST['billing_cf_id'] )
        wc_add_notice( __( '<strong>Cod Fiscal</strong> is a required field.', 'theme_domain' ), 'error' );
}

// Adding/Updating meta data to the order with the custom-fields values
add_action( 'woocommerce_checkout_update_order_meta', 'ba_custom_checkout_field_update_order_meta' );
function ba_custom_checkout_field_update_order_meta( $order_id ) {

    $billing_company = $_POST['billing_company'];
    $billing_ser_id  = $_POST['billing_ser_id'];
    $billing_bt_id   = $_POST['billing_bt_id'];
    $billing_ib_id   = $_POST['billing_ib_id'];
    $billing_cf_id   = $_POST['billing_cf_id'];

    // For Individual resetting billing company to "" (no value) instead of 'no'
    if ( !empty($billing_company) && 'no' == $billing_company )
        update_post_meta( $order_id, '_billing_company', '' );

    if ( !empty($billing_ser_id) )
        update_post_meta( $order_id, '_billing_ser_id', sanitize_text_field( $billing_ser_id ) );

    // Adding/updating data only for companies
    if ( !empty($billing_bt_id) && 'no' != $billing_bt_id )
        update_post_meta( $order_id, '_billing_bt_id', sanitize_text_field( $billing_bt_id ) );

    // Adding/updating data only for companies
    if ( !empty($billing_ib_id) && 'no' != $billing_ib_id )
        update_post_meta( $order_id, '_billing_ib_id', sanitize_text_field( $billing_ib_id ) );

    // Adding/updating data only for companies
    if ( !empty($billing_cf_id) && 'no' != $billing_cf_id )
        update_post_meta( $order_id, '_billing_cf_id', sanitize_text_field( $billing_cf_id ) );
}


// Display custom-field Title/values on the order edit page
add_action( 'woocommerce_admin_order_data_after_billing_address', 'ba_custom_checkout_field_display_admin_order_meta', 10, 1 );
function ba_custom_checkout_field_display_admin_order_meta( $order ){

    $output = '';
    $billing_ser_id = get_post_meta( $order->id, '_billing_ser_id', true );
    $billing_bt_id  = get_post_meta( $order->id, '_billing_bt_id',  true );
    $billing_ib_id  = get_post_meta( $order->id, '_billing_ib_id',  true );
    $billing_cf_id  = get_post_meta( $order->id, '_billing_cf_id',  true );

    if ( !empty($billing_ser_id) ){
        $output .= '<p><strong>' . __( 'Nr. Reg. Comert', 'theme_domain' ) . ':</strong> ' . $billing_ser_id . '</p>';
    }

    if ( !empty($billing_bt_id) && 'no' != $billing_bt_id ){
        $output .= '<p><strong>' . __( 'Banca', 'theme_domain' ) . ':</strong> ' . $billing_bt_id . '</p>';
    }

    if ( !empty($billing_ib_id) && 'no' != $billing_ib_id ){
        $output .= '<p><strong>' . __( 'IBAN', 'theme_domain' ) . ':</strong> ' . $billing_ib_id . '</p>';
    }

    if ( !empty($billing_cf_id) && 'no' != $billing_cf_id ){
        $output .= '<p><strong>' . __( 'Cod Fiscal', 'theme_domain' ) . ':</strong> ' . $billing_cf_id . '</p>';
    }

    echo $output;
}

To display the data on the customer order view, on Thankyou page, My account order view and on email notifications, add this 2 code snippets in your function.php file:

// Displaying data on order view in "customer details" zone
add_action('woocommerce_order_details_after_customer_details','ba_add_values_to_order_item_meta', 10, 1 );
function ba_add_values_to_order_item_meta( $order ) {

    $output = '';
    $billing_ser_id = get_post_meta( $order->id, '_billing_ser_id', true );
    $billing_bt_id  = get_post_meta( $order->id, '_billing_bt_id',  true );
    $billing_ib_id  = get_post_meta( $order->id, '_billing_ib_id',  true );
    $billing_cf_id  = get_post_meta( $order->id, '_billing_cf_id',  true );

    if ( !empty($billing_ser_id) )
        $output .= '
        <tr>
            <th>' . __( "Nr. Reg. Comert:", "woocommerce" ) . '</th>
            <td>' . $billing_ser_id . '</td>
        </tr>';

    if ( !empty($billing_bt_id) && 'no' != $billing_bt_id )
        $output .= '
        <tr>
            <th>' . __( "Banca:", "woocommerce" ) . '</th>
            <td>' . $billing_bt_id . '</td>
        </tr>';

    if ( !empty($billing_ib_id) && 'no' != $billing_ib_id )
        $output .= '
        <tr>
            <th>' . __( "IBAN:", "woocommerce" ) . '</th>
            <td>' . $billing_ib_id . '</td>
        </tr>';

    if ( !empty($billing_cf_id) && 'no' != $billing_cf_id )
        $output .= '
        <tr>
            <th>' . __( "Cod Fiscal:", "woocommerce" ) . '</th>
            <td>' . $billing_cf_id . '</td>
        </tr>';

    echo $output;
}


// Displaying data on email notifications
add_action('woocommerce_email_customer_details','ba_add_values_to_emails_notifications', 15, 4 );
function ba_add_values_to_emails_notifications( $order, $sent_to_admin, $plain_text, $email ) {

    $output = '<ul>';
    $billing_ser_id = get_post_meta( $order->id, '_billing_ser_id', true );
    $billing_bt_id  = get_post_meta( $order->id, '_billing_bt_id',  true );
    $billing_ib_id  = get_post_meta( $order->id, '_billing_ib_id',  true );
    $billing_cf_id  = get_post_meta( $order->id, '_billing_cf_id',  true );

    if ( !empty($billing_ser_id) )
        $output .= '<li><strong>' . __( "Nr. Reg. Comert:", "woocommerce" ) . '</strong> <span class="text">' . $billing_ser_id . '</span></li>';

    if ( !empty($billing_bt_id) && 'no' != $billing_bt_id )
        $output .= '<li><strong>' . __( "Banca:", "woocommerce" ) . '</strong> <span class="text">' . $billing_bt_id . '</span></li>';

    if ( !empty($billing_ib_id) && 'no' != $billing_ib_id )
        $output .= '<li><strong>' . __( "IBAN:", "woocommerce" ) . '</strong> <span class="text">' . $billing_ib_id . '</span></li>';

    if ( !empty($billing_cf_id) && 'no' != $billing_cf_id )
        $output .= '<li><strong>' . __( "Cod Fiscal:", "woocommerce" ) . '</strong> <span class="text">' . $billing_cf_id . '</span></li>';
        $output .= '</ul>';

    echo $output;
}

Javascript cfields.js code (external file):

// This file named "cfields.js" goes in a subfolder "js" of your active child theme or theme

jQuery(document).ready(function($){

    // Common Serial ID field
    if(! $("#billing_ser_id_field").hasClass("validate-required") ){
        $("#billing_ser_id_field").addClass("validate-required");
    }


    // The 4 Fields to hide at start (if not "Persoana Juridica")
    if($("#billing_status option:selected").val() == "1"){
        $('#billing_company_field').hide(function(){
            $(this).removeClass("validate-required");
            $(this).removeClass("woocommerce-validated");
            $('#billing_company').val("no");
        });
        $('#billing_bt_id_field').hide(function(){
            $(this).removeClass("validate-required");
            $(this).removeClass("woocommerce-validated");
            $('#billing_bt_id').val("no");
        });
        $('#billing_ib_id_field').hide(function(){
            $(this).removeClass("validate-required");
            $(this).removeClass("woocommerce-validated");
            $('#billing_ib_id').val("no");
        });
        $('#billing_cf_id_field').hide(function(){
            $(this).removeClass("validate-required");
            $(this).removeClass("woocommerce-validated");
            $('#billing_cf_id').val("no");
        });
     }

    // Action with the selector (Showing/hiding and adding/removing classes)
    $("#billing_status").change(function(){
        // For "Persoana Juridica"
        if($("#billing_status option:selected").val() == "2")
        {
            $('#billing_company_field').show(function(){
                $(this).addClass("validate-required");
                $('#billing_company').val("");
            });
            $('#billing_bt_id_field').show(function(){
                $(this).children('label').append( ' <abbr class="required" title="required">*</abbr>' );
                $(this).addClass("validate-required");
                $('#billing_bt_id').val("");
            });
            $('#billing_ib_id_field').show(function(){
                $(this).children('label').append( ' <abbr class="required" title="required">*</abbr>' );
                $(this).addClass("validate-required");
                $('#billing_ib_id').val("");
            });
            $('#billing_cf_id_field').show(function(){
                $(this).children('label').append( ' <abbr class="required" title="required">*</abbr>' );
                $(this).addClass("validate-required");
                $('#billing_cf_id').val("");
            });
        }
        // For "Persoana Fizica"
        else if($("#billing_status option:selected").val() == "1")
        {
            $('#billing_company_field').hide(function(){
                $(this).removeClass("validate-required");
                $(this).removeClass("woocommerce-validated");
                $('#billing_company').val("no");
            });
            $('#billing_bt_id_field').hide(function(){
                $(this).children("abbr.required").remove();
                $(this).removeClass("validate-required");
                $(this).removeClass("woocommerce-validated");
                $('#billing_bt_id').val("no");
            });
            $('#billing_ib_id_field').hide(function(){
                $(this).children("abbr.required").remove();
                $(this).removeClass("validate-required");
                $(this).removeClass("woocommerce-validated");
                $('#billing_ib_id').val("no");
            });
            $('#billing_cf_id_field').hide(function(){
                $(this).children("abbr.required").remove();
                $(this).removeClass("validate-required");
                $(this).removeClass("woocommerce-validated");
                $('#billing_cf_id').val("no");
            });
        }

    });

});

All this code has been tested and works