Skip to content
Advertisement

Issue adding and processing a custom checkout select field in WooCommerce

I am trying to add a dropdown field at checkout which needs to be validated before order submission and stored in the order for admin to view in order details. But for some reason even after i select the dropdown option, it says a value must be selected for the field.

add_filter( 'woocommerce_after_checkout_form', 'custom_checkout_fields' );

function custom_checkout_fields( $checkout ) {

    // The selector
    woocommerce_form_field( 'allow_substitute', array(
        'type'        => 'select',
        'required'    => true,
        'class'       => array('my-field-class form-row-wide'),
        'label'       => __('Allow Product substitution when a cigar is out of stock?', 'my_theme_slug'),
        'options'     => array(
            '' => __('Choose an option', 'my_theme_slug'),
            'option1' => 'Allow product substitution (When a cigar is out of stock, a similar cigar will be shipped.',
            'option2' => 'Call me before making a product substitution',
            'option3' => 'Refund the cigar order value that is out of stock'
        )
    ), $checkout->get_value( 'allow_substitute' ));

    echo '</div>';
}

// Process the checkout
add_action('woocommerce_checkout_process', 'custom_checkout_field_process');
function custom_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( ! $_POST['allow_substitute'] ) // the selector
        wc_add_notice( __( 'Please select a value for "Product Substitution?" field.' ), '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['allow_substitute'] ) ) {
        update_post_meta( $order_id, 'allow_substitute', sanitize_text_field( $_POST['allow_substitute'] ) );
    }
}

Advertisement

Answer

You can’t add a custom checkout field outside the checkout form, as it’s not posted… Use the following complete replacement code instead:

// Function with the array of options key / values pairs for the select field
function get_allow_substitute_field_options() {
    $text_domain = 'my_theme_slug';

    return array(
        ''  => __('Choose an option', $text_domain),
        '1' => __('Allow product substitution (When a cigar is out of stock, a similar cigar will be shipped.', $text_domain),
        '2' => __('Call me before making a product substitution', $text_domain),
        '3' => __('Refund the cigar order value that is out of stock', $text_domain)
    );
}

// Display the select field
add_filter( 'woocommerce_checkout_after_order_review', 'custom_checkout_select_field', 50 );
function custom_checkout_select_field() {
    $text_domain = 'my_theme_slug';

    // The select field
    woocommerce_form_field( 'allow_substitute', array(
        'type'     => 'select',
        'required' => true,
        'class'    => array('my-field-class form-row-wide'),
        'label'    => __('Allow Product substitution when a cigar is out of stock?', $text_domain),
        'options'  => get_allow_substitute_field_options(),
    ), WC()->checkout->get_value( 'allow_substitute' ));

    echo '</div>';
}

// Checkout select field validation
add_action('woocommerce_after_checkout_validation', 'custom_checkout_select_field_validation', 10, 2 );
function custom_checkout_select_field_validation( $data, $errors ) {
    // Check if set, if its not set add an error.
    if ( isset($_POST['allow_substitute']) && empty($_POST['allow_substitute']) ) {
        $errors->add( 'validation', __( 'Please select a value for "Product Substitution?" field.' ) );
    }
}

// Save selected option as order meta data
add_action( 'woocommerce_checkout_create_order', 'custom_checkout_field_update_order_meta' );
function custom_checkout_field_update_order_meta( $order ) {
    if ( isset($_POST['allow_substitute']) && ! empty($_POST['allow_substitute']) ) {
        $order->update_meta_data( 'allow_substitute', sanitize_text_field( $_POST['allow_substitute'] ) );
    }
}

// Display "allow_substitute" option value on the order edit pages under billing section
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_allow_substitute_field_value_in_admin_orders', 10, 1 );
function display_allow_substitute_field_value_in_admin_orders($order){
    $field_key = $order->get_meta('allow_substitute');

    if ( ! empty($field_key) ) {
        $field_options = get_allow_substitute_field_options();
        $field_value   = $field_options[$field_key];

        echo '<p>
            <strong>'.__('Product substitution').':</strong> <br>
            <small>' . $field_value . '</small>
        </p>';
    }
}

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

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement