Akberov
Akberov

Reputation: 164

Display custom checkout field value on admin order detail section in Woocommerce

Hello I'm trying to display the custom checkout field in the admin order details page. My Custom field is Delivery Option and it allows the user to pick the to pick a value from checkbox. I use the code below following the similar topics about this, but it seems something is wrong with my code.

add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_additional_field', 20 );
function checkout_shipping_additional_field()
{
    $domain  = 'wocommerce';
    $default = 'option 1';

    echo '<tr class="additional-shipping-fields"><th>' . __('Delivery Time', $domain) . '</th><td>';

    // Add a custom checkbox field
    woocommerce_form_field( 'custom_radio_field', array(
        'type' => 'select',
        'class' => array( 'form-row-wide' ),
        'options' => array(
            'option 1' => __('10:04 : 13:04 ', $domain),

        ),
        'default' => $default,
    ), $default );

    echo '</td></tr>';
}

//update order meta
add_action('woocommerce_checkout_update_order_meta', 'gon_update_order_meta_business_address');

function gon_update_order_meta_business_address( $order_id ) {
    if ($_POST['custom_radio_field']) update_post_meta( $order_id, 'Business Address?', 
    esc_attr($_POST['custom_radio_field']));
}

// Display field value on the admin order edit page
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'custom_checkout_field_display_admin_order_meta', 10, 1 );
function custom_checkout_field_display_admin_order_meta( $order ){
    $delivery_time = get_post_meta( $order->get_id(), 'Delivery Time', true );
    if( ! empty( $delivery_time ) )
        echo '<p><strong>'.__('Delivery Time', 'woocommerce').': </strong> ' . $delivery_time . '</p>';
}

Upvotes: 2

Views: 2464

Answers (2)

Elron
Elron

Reputation: 1455

Based on @LoicTheAztec answer, if you want multiple fields without re-writing the functions for every field (DRY), you can use this class (by adding it to your functions.php):

/**
 * Add a custom field to the woocommerce checkout page
 * https://stackoverflow.com/q/52098807/
 */
class WOO_Add_Checkout_Field
{
    public function __construct($options)
    {

        $this->field_name = $options['field_name'];
        $this->label = $options['label'];
        $this->placeholder = $options['placeholder'];
        $this->required = $options['required'];

        if ($this->field_name && $this->label && $this->placeholder) {
            add_action('woocommerce_after_order_notes', [$this, 'customise_checkout_field']);
            add_action('woocommerce_checkout_update_order_meta', [$this, 'custom_checkout_field_update_order_meta'], 10, 1);
            add_action('woocommerce_admin_order_data_after_billing_address', [$this, 'display_custom_field_on_order_edit_pages'], 10, 1);
        } else {
            die("Error in WOO_Add_Checkout_Field \$options: \n\n" . var_dump($options));
        }
    }
    public function customise_checkout_field($checkout)
    {
        echo '<div id="customise_checkout_field">';
        // echo '<h2>' . __('Heading') . '</h2>';
        woocommerce_form_field($this->field_name, array(
            'type' => 'text',
            'class' => array(
                'my-field-class form-row-wide'
            ),
            'label' => $this->label,
            'placeholder' => $this->placeholder,
            'required' => $this->required,
        ), $checkout->get_value($this->field_name));
        echo '</div>';
    }

    public function custom_checkout_field_update_order_meta($order_id)
    {
        if (!empty($_POST[$this->field_name]))
            update_post_meta($order_id, $this->field_name, $_POST[$this->field_name]);
        else
            update_post_meta($order_id, $this->field_name, 0);
    }


    public function display_custom_field_on_order_edit_pages($order)
    {
        $field = $order->get_meta($this->field_name);
        if (!empty($field)) {
            echo '<p><strong style="display:block" title="' . $this->placeholder . '">' . $this->label . ': </strong><span>';
            echo $field;
            echo '</span></p>';
        }
    }
}

And use it as many times as you'd like:

$my_custom_field_1 = new WOO_Add_Checkout_Field([
    'field_name' => 'my_custom_field_1',
    'label' => __('My First Field'),
    'placeholder' => __('Please write something in field 1...'),
    'required' => false,
]);

$my_custom_field_2 = new WOO_Add_Checkout_Field([
    'field_name' => 'my_custom_field_2',
    'label' => __('My Second Field'),
    'placeholder' => __('Please write something in field 2...'),
    'required' => false,
]);

$my_custom_field_3 = new WOO_Add_Checkout_Field([
    'field_name' => 'my_custom_field_3',
    'label' => __('My Third Field'),
    'placeholder' => __('Please write something in field 3...'),
    'required' => false,
]);

// and so on...

Please note:

  • The custom field will show up in admin area ONLY if it was not sent empty
  • You can customize this code how you like

Upvotes: 0

LoicTheAztec
LoicTheAztec

Reputation: 253773

There is some mistakes, so I have revisited your code. I have also replaced some hooks. Try the following:

// HERE set your the options array for your select field.
function delivery_time_options(){
    $domain = 'woocommerce';
    return array(
        '1' => __('10:04 : 13:04 ', $domain),
        '2' => __('14:04 : 16:04 ', $domain), // <== Added for testing
    );
}

// Display a custom select field after shipping total line
add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_additional_field', 20 );
function checkout_shipping_additional_field(){
    $domain = 'woocommerce';

    echo '<tr class="additional-shipping-fields"><th>' . __('Delivery Time', $domain) . '</th><td>';

    // Add a custom select field
    woocommerce_form_field( 'delivery_time', array(
        'type' => 'select',
        'class' => array( 'form-row-wide' ),
        'options' => delivery_time_options(),
    ), '' );

    echo '</td></tr>';
}

// Save custom field as order meta data
add_action('woocommerce_checkout_create_order', 'save_custom_field_order_meta', 22, 2 );
function save_custom_field_order_meta( $order, $data ) {
    if ( isset($_POST['delivery_time']) ) {
        $options    = delivery_time_options(); // Get select options array
        $option_key = esc_attr($_POST['delivery_time']); // The selected key

        $order->update_meta_data( '_delivery_time', $options[$option_key] ); // Save
    }
}

// Display a custom field value on the admin order edit page
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_custom_meta_data_in_backend_orders', 10, 1 );
function display_custom_meta_data_in_backend_orders( $order ){
    $domain = 'woocommerce';

    $delivery_time = $order->get_meta('_delivery_time');
    if( ! empty( $delivery_time ) )
        echo '<p><strong>'.__('Delivery Time', $domain).': </strong> ' . $delivery_time . '</p>';
}

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

Upvotes: 2

Related Questions