2

I'm trying to re-order 2 custom checkout fields added with the help of woocommerce_checkout_init filter, just that when I apply woocommerce_checkout_fields filter to re-order fields, it doesn't recognize them and they are null.
I think it's because the filter woocommerce_checkout_init goes after woocommerce_checkout_fields.

How Can I solve this?

Here is my code:

add_action( 'woocommerce_checkout_init', 'wc_add_confirm_email_checkout', 10, 2 );
function wc_add_confirm_email_checkout( $checkout ) {
    $checkout->checkout_fields['billing']['billing_email2'] = array(
        'type'              => 'text',
        'label'             => __( 'Confirm Email Address', 'woocommerce' ),
        'required'          => true,
        'placeholder'       => _x( 'Confirm Email Address', 'placeholder', 'woocommerce' )
    );
}
add_action( 'woocommerce_checkout_init', 'wc_add_confirm_password_checkout', 10, 2 );
function wc_add_confirm_password_checkout( $checkout ) {
    //var_dump($checkout->checkout_fields);
    if ( get_option( 'woocommerce_registration_generate_password' ) == 'no' ) {
        $checkout->checkout_fields['account']['account_password2'] = array(
            'type'              => 'password',
            'label'             => __( 'Confirm password', 'woocommerce' ),
            'required'          => true,
            'placeholder'       => _x( 'Confirm Password', 'placeholder', 'woocommerce' )
        );
    }
}

add_filter('woocommerce_checkout_fields','reorder_woo_fields');
function reorder_woo_fields($fields) {
    $fields2['billing']['billing_first_name'] = $fields['billing']['billing_first_name'];
    $fields2['billing']['billing_last_name'] = $fields['billing']['billing_last_name'];
    $fields2['billing']['billingooglg_email'] = $fields['billing']['billing_email'];
    $fields2['billing']['billing_email2'] = $fields['billing']['billing_email2'];
    $fields2['billing']['account_password'] = $fields['account']['account_password'];
    $fields2['billing']['account_password2'] = $fields['account']['account_password2'];
    $fields2['billing']['billing_address_1'] = $fields['billing']['billing_address_1'];
    $fields2['billing']['billing_postcode'] = $fields['billing']['billing_postcode'];
    var_dump($fields2);
    //return $fields2;
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Adrian
  • 2,273
  • 4
  • 38
  • 78
  • Anyone any ideas, appreciate the upvote. – Adrian Jul 08 '16 at 10:49
  • @LoicTheAztec Thanks for helping, it seams that re-ordering part did the trick, so replaced that with the loop and array you gave me (remove some fields as per my code) and it added the email address and confirm password where I wanted. – Adrian Jul 08 '16 at 14:56
  • Question for my curiosity: So it was possible melting checkout billing fields with checkout account fields? … If you want to update my answer your are welcome. You can add an update at the end with your code. Thanks – LoicTheAztec Jul 08 '16 at 15:02
  • Ah no I added them separate, maybe i can do this my adding them into a single array like the account array to change it to billing array. – Adrian Jul 08 '16 at 15:11
  • Possible duplicate of [Reorder Woocommerce checkout fields](https://stackoverflow.com/questions/45200360/reorder-woocommerce-checkout-fields) – Yahya Hussein Jan 15 '18 at 09:25

3 Answers3

8

For WooCommerce 3+ (update):

Since WooCommerce 3.0 checkout fields have changed a little bit so is not possible to reorder fields as before.

There is a new 'priority' argument that handle fields order, for checkout fields and my account fields as well.

Here is fully functional example for WooCommerce 3+:

// REORDERING CHECKOUT BILLING FIELDS (WOOCOMMERCE 3+)
add_filter( "woocommerce_checkout_fields", "reordering_checkout_fields", 15, 1 );
function reordering_checkout_fields( $fields ) {

    ## ---- 1. REORDERING BILLING FIELDS ---- ##

    // Set the order of the fields
    $billing_order = array(
        'billing_first_name',
        'billing_last_name',
        'billing_email',
        'billing_phone',
        'billing_company',
        'billing_address_1',
        'billing_address_2',
        'billing_postcode',
        'billing_city',
        'billing_state',
        'billing_country'
    );

    $count = 0;
    $priority = 10;

    // Updating the 'priority' argument
    foreach($billing_order as $field_name){
        $count++;
        $fields['billing'][$field_name]['priority'] = $count * $priority;
    }

    ## ---- 2. CHANGING SOME CLASSES FOR BILLING FIELDS ---- ##

    $fields['billing']['billing_email']['class'] = array('form-row-first');
    $fields['billing']['billing_phone']['class'] = array('form-row-last');

    $fields['billing']['billing_postcode']['class'] = array('form-row-first');
    $fields['billing']['billing_city']['class'] = array('form-row-last');
    
    ## ---- RETURN THE BILLING FIELDS CUSTOMIZED ---- ##

    return $fields;
}

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


Before WooCommerce 3

I am not completely sure, but you there are some things that you can't do like merging billing fields with account fields. If you want to do that is going to be much more complicated than what you are trying to do here. In that case you will need to rewrite/create some checkout templates…

Another thing is that billing_email and billing_phone are sharing the same line together with 'class' => 'form-row-first' and 'class' => 'form-row-last'. When not this class is define 'class' => 'form-row-wide'… So you are going to need overriding these 'class' too.

After that you dont need to use 'woocommerce_checkout_init' hook…
You can still use 'woocommerce_checkout_fields'.
Also you can merge all of them in one function this way:

/*
 * Creating, overriding and reordering custom fields.
 */
add_filter( "woocommerce_checkout_fields", "custom_override_checkout_fields", 11, 1 );
function custom_override_checkout_fields( $fields ) {

    // Creating 'billing_email2' field
    $fields['billing']['billing_email2'] = array(
        'type'          => 'text',
        'label'         => __( 'Confirm Email Address', 'woocommerce' ),
        'placeholder'   => _x( 'Confirm Email Address', 'placeholder', 'woocommerce' ),
        'required'      => true,
        'class'         => array('form-row-last'),
        'clear'         => true
    );

    // =======> I don't really know if you need this one  <========
    // it already exist (see in first reference link at bottom).

    // Creating 'account_password2' field 
    if ( get_option( 'woocommerce_registration_generate_password' ) == 'no' ) {
        $fields['account']['account_password2'] = array(
            'type'          => 'password',
            'label'         => __( 'Confirm password', 'woocommerce' ),
            'placeholder'   => _x( 'Confirm Password', 'placeholder', 'woocommerce' ),
            'required'      => true,
            'class'         => array('form-row-wide') //,
            // 'clear'         => true
        );
    }

    // Overriding existing billing_phone field 'class' property 
    $fields['billing']['billing_phone']['class'] = array('form-row-wide');


    // Reordering billing fields
    $order = array(
        "billing_first_name",
        "billing_last_name",
        "billing_email",
        "billing_email2",
        "billing_phone",
        "billing_company",
        "billing_address_1",
        "billing_address_2",
        "billing_postcode",
        "billing_country"
    );

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

    $fields["billing"] = $ordered_fields;

    return $fields;
}

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

As I have said before, I think that you can't merge billing fields with account fields.
As 'account_password2' already exist if you refer to official documentation (see below in first reference link), you may not need to create it. You will have to test this and to fine tune it. But this is the way to do it.


References:

Community
  • 1
  • 1
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Appreciate the answer, one more thing, if I want to add a new section lets say Your details, with fields like name, email, phone and country do I need to edit form-checkout.php or is it possible via a function and a hook. – Adrian Jul 09 '16 at 14:28
  • @user3467855 Not sure… but in checkout template you have only 4 fields sections: 'billing', 'shipping' 'account' and 'notes'. It depends also where you want to have this. You can't have the same fields 2 times (for example one in billing section and another time to an other section. Name, Email and phone already exists… So that is the problem... – LoicTheAztec Jul 09 '16 at 14:37
  • @LoicTheAztec Hi, I try to use this code for reordering checkout fields. But I have the same issue, some filed "jumb" when the page is full upload. The sample in this video: https://www.loom.com/share/82037629405440eea9ddf3115088e279 Please help me to sove this issue, I really can not got it what happens. – Victor Sokoliuk Dec 08 '20 at 08:15
  • You can modify the code a little bit to programmatically get the fields and only put the new field at any exact location you want. Where 'billing_email2' can be placed before first_name. How does the priority parameter override this reordering? – pensebien Feb 15 '22 at 18:24
2

Notice!

Woocommerce has made some changes and for arranging address fields you should use 'woocommerce_default_address_fields' filter.

add_filter( 'woocommerce_default_address_fields', 'custom_override_default_locale_fields' );
function custom_override_default_locale_fields( $fields ) {
    $fields['state']['priority'] = 5;
    $fields['address_1']['priority'] = 6;
    $fields['address_2']['priority'] = 7;
    return $fields;
}

Reorder Woocommerce checkout fields

A mohseni
  • 41
  • 3
1

To Add to the accepted answer...

If you need to move form fields from one field group to another, for example moving a shipping field into billing or an account field into billing, you can do the following.

function move_password_field($checkout_fields){
    // Move Account Password into Billing
    $checkout_fields['billing']['account_password'] = $checkout_fields['account']['account_password']; 

    // Remove Password from Billing
    unset($checkout_fields['account']['account_password']);

    return $checkout_fields;
}

add_filter('woocommerce_checkout_fields', 'move_password_field', 999);
RiddleMeThis
  • 1,345
  • 4
  • 16
  • 29