Required custom WooCommerce checkout fields don't validate entered value

14,133

Solution 1

As you can read in woocommerce_before_checkout_form hook, it's before checkout form (so outside the checkout form). For this reason this custom field can't work in this hook.

You can use instead woocommerce_checkout_update_order_meta action hook, making some little changes in your code as there is no $checkout argument available in it.

This will display the field "at the top of the page, before the billing fields"

enter image description here

So your complete code should be now:

/**
 * Add the field to the checkout
 */
add_action( 'woocommerce_checkout_before_customer_details', 'my_custom_checkout_fields' );

function my_custom_checkout_fields() {

    echo '<div id="my_custom_checkout_field" class="col4-set"><h2>' . __('name') . '</h2>';

    woocommerce_form_field( 'developer_name', array(
        'type'          => 'text',
        'class'         => array('developer_name-class form-row form-row-first'),
        'label'         => __('name'),
        'placeholder'   => __('fill in your name'),
        'required'      => true,
    ), WC()->checkout->get_value( 'developer_name' ));

    echo '</div>';

}

/**
 * Process the checkout
 */
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');

function my_custom_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( ! $_POST['developer_name'] )
        wc_add_notice( __( 'Please fill in your name.' ), 'error' );
}


// Update the order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta', 10, 1 );
function my_custom_checkout_field_update_order_meta( $order_id ) {
    if ( ! empty( $_POST['developer_name'] ) ) {
        update_post_meta( $order_id, 'Developer name', sanitize_text_field( $_POST['developer_name'] ) );
    }
}

// Display the custom-field in orders view
add_action( 'woocommerce_order_details_after_customer_details', 'display_my_custom_field_in_orde_details', 10, 1 );
function display_my_custom_field_in_orde_details( $order ) {

    $developer_name = get_post_meta( $order->get_id(), 'Developer name',  true );

    if ( ! empty( $developer_name ) ):
    ?>
        <table class="woocommerce-table woocommerce-table--customer-details shop_table customer_details">
            <tbody><tr>
                <th>Developer name:</th>
                <td><?php echo $developer_name; ?></td>
            </tr></tbody>
        </table>
    <?php
    endif;
}

This code goes in function.php file of your active child theme (or theme) or also in any plugin file.

This code is tested and works for WooCommerce version 3.0+

Solution 2

**/* If You Have Created Your Custom Field at the checkout page */**

add_action( 'woocommerce_after_checkout_validation', 'shipping_time_optionss', 9999, 2);
function shipping_time_optionss( $fields, $errors ){
    // if any validation errors
    if ( empty( $_POST['woo_shipping_time'] ) ) {
        $errors->add( 'woocommerce_password_error', __( 'Please Select Shipping Time Option.' ) );
    } `enter code here`
} 

Solution 3

You try this code. Tested Ok

add_action( 'woocommerce_billing_fields', 'my_custom_checkout_fields' );

function my_custom_checkout_fields( $fields ) {

   $fields['billing_developer_name'] = array(
    'label'       => __('Developer name', 'woocommerce'),            
    'placeholder' => _x('Developer name', 'placeholder', 'woocommerce'),  
    'required'    => TRUE,             
    'clear'       => false,             
    'type'        => 'text',              
    'class'       => array('my-css')    
    );

 return $fields;

}

You can arrange it with this snippet

add_filter("woocommerce_checkout_fields", "order_fields");

function order_fields($fields) {

    $order = array(
        "billing_developer_name",
        "billing_first_name", 
        "billing_last_name", 
        "billing_company", 
        "billing_address_1", 
        "billing_address_2", 
        "billing_postcode", 
        "billing_country", 
        "billing_email", 
        "billing_phone"

    );
    foreach($order as $field)
    {
        $ordered_fields[$field] = $fields["billing"][$field];
    }

    $fields["billing"] = $ordered_fields;
    return $fields;

}

See screenshot

Share:
14,133
buzibuzi
Author by

buzibuzi

Updated on June 05, 2022

Comments

  • buzibuzi
    buzibuzi almost 2 years

    I'm adding WooCommerce custom checkout fields in a Storefront child theme functions.php file.
    They have a "required" attribute.
    The aim is to have these fields appear at the top of the page, before the billing fields.

    when clicking the submit button to proceed to payment, I'm getting the required custom field validation error ('please fill in your name') and can't continue with payment, even though filling the field with valid data.

    Any clue how to fix this or where to start debugging ?

    here is the code in functions.php:

    add_action( 'woocommerce_before_checkout_form', 'my_custom_checkout_fields' );
    
    function my_custom_checkout_fields( $checkout ) {
    
        echo '<div id="my_custom_checkout_field" class="col4-set"><h2>' . __('name') . '</h2>';
    
        woocommerce_form_field( 'developer_name', array(
            'type'          => 'text',
            'class'         => array('developer_name-class form-row form-row-first'),
            'label'         => __('name'),
            'placeholder'   => __('fill in your name'), 
            'required'      => true,
            ), $checkout->get_value( 'developer_name' ));                               
    
        echo '</div>';
    
    }
    
    /**
     * Process the checkout
     */
    add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
    
    function my_custom_checkout_field_process() {
        // Check if set, if its not set add an error.
    if ( ! $_POST['developer_name'] )
            wc_add_notice( __( 'please fill in your name' ), 'error' );  
    }
    

    I tried the following but none of them helped:

    1. changing:

    if ( ! $_POST['developer_name'] ) 
    

    to

    if ( empty( $_POST['developer_name']) )
    

    2. changing the trigger from:

     add_action( 'woocommerce_before_checkout_form', 'my_custom_checkout_fields' ); 
    

    to

    add_action( 'woocommerce_after_checkout_form', 'my_custom_checkout_fields' );
    

    3. updating to latest Woocomerce 3.0.5 version

    I'm running Wordpress 4.7.4
    additional related active plugins:
    Uni CPO - WooCommerce Options and Price Calculation Formulas

  • buzibuzi
    buzibuzi almost 7 years
    i forgot to make it clear. my aim is to have these fields located before the billing information. that means on the top of the page. your solution is good but the custom fields appear below the billing fields.
  • mujuonly
    mujuonly almost 7 years
    @buzibuzi : Updated
  • buzibuzi
    buzibuzi almost 7 years
    it works, can these field-set have a title above and below them ? with my checkout code i have a H2 title printed above them. "Billing Details" title comes below them, so have some kind of a separator between the fields.
  • buzibuzi
    buzibuzi almost 7 years
    great approach, thank you. @LoicTheAztec answer fits my need more because it keeps the custom fields on the top as a separate section from the Billing section
  • buzibuzi
    buzibuzi almost 7 years
    Thank you ! this answers the question and works well