Reorder Woocommerce checkout fields

Viewed 21253

I am trying to reorder the billing fields on the checkout page but everything I tried so far is not working.

Here is the snippet I am currently trying:

add_filter("woocommerce_checkout_fields", "order_fields");

function order_fields($fields) {
  $order = array(
    "billing_first_name", 
    "billing_last_name", 
    "billing_country", 
    "billing_state", 
    "billing_address_1", 
    "billing_address_2", 
    "billing_email", 
    "billing_phone"
  );

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

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

Could something be overriding this snippet, because it used to work for me.

6 Answers

The ordering(sorting) works on address-i18n.min.js not in php code.

enter image description here

In my case, I did something wrong on my js code. So, the ordering didn't work well( javascript stop there ).

Please check dev console and js error.

And this is php code which change only priority.

function rpf_edit_default_address_fields($fields) {

  /* ------ reordering ------ */
  $fields['country']['priority'] = 10;
  $fields['first_name']['priority'] = 20;
  $fields['last_name']['priority'] = 30;
  $fields['address_1']['priority'] = 40;
  $fields['address_2']['priority'] = 50;
  $fields['city']['priority'] = 60;
  $fields['state']['priority'] = 70;
  $fields['postcode']['priority'] = 80;

  return $fields;
}
add_filter( 'woocommerce_default_address_fields', 'rpf_edit_default_address_fields', 100, 1 );

Good Luck!

As @Byeongin correctly mentions in his answer, apart from the backend ordering (that @Frits answer covers) there is also ordering that happens via JavaSrcipt in the front-end when the user selects specific countries from the dropdown menu.

If you also want to stop this front-end reordering from happening, the best solution I've encountered so far would be to hook into the woocommerce_get_country_locale filter and remove the priority overrides that are added there.

Something like the following will do the trick (tested with WooCommerce v3.5.4):

add_filter( 'woocommerce_get_country_locale', function( $locale ) {
    foreach ( $locale as $country_code => $locale_fields ) {
        foreach ( $locale_fields as $field_key => $field_options ) {
            if ( isset( $field_options['priority'] ) ) {
                unset( $field_options['priority'] );
            }

            $locale[ $country_code ][ $field_key ] = $field_options;
        }
    }

    return $locale;
} );

Change native woocommerce class This method works with me. In fact, woocommerce uses a class : form-row-first (css: float left) end form-row-last: float right. If you change the priority 2 to 1 but ccs class is form-row-last, the field will still be on the right.

add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields',1 );
function custom_override_checkout_fields( $fields ) {
    $fields['billing']['billing_email']['priority'] = 3;
    $fields['billing']['billing_email']['label'] = mb_strtoupper("adresse email");
    $fields['billing']['billing_email']['class'] = array('form-left');
    $fields['billing']['billing_company']['priority'] = 5;
    $fields['billing']['billing_company']['label'] = mb_strtoupper("entreprise");
    $fields['billing']['billing_company']['required'] = false;
    $fields['billing']['billing_company']['class'] = array('form-left');
    $fields['billing']['billing_phone']['priority'] = 6;
    $fields['billing']['billing_phone']['label'] = mb_strtoupper("téléphone");
    $fields['billing']['billing_phone']['required'] = false;
    $fields['billing']['billing_phone']['class'] = array('form-right');
    $fields['billing']['billing_phone']['validate'] = array('phone');
    $fields['shipping']['shipping_company']['priority'] = 3;
    $fields['shipping']['shipping_company']['label'] = mb_strtoupper("entreprise");
    $fields['shipping']['shipping_company']['required'] = false;
    $fields['shipping']['shipping_company']['class'] = array('form-left');

    return $fields;
}

Others fields like first_name, last_name, address_1, address-2, post_code, city, country, state must be placed in this filter

add_filter( 'woocommerce_default_address_fields','custom_override_default_locale_fields');
function custom_override_default_locale_fields( $fields ) {
    $fields['last_name']['priority'] = 1;
    $fields['last_name']['label'] = mb_strtoupper("nom");
    $fields['last_name']['class'] = array('form-left');
    $fields['first_name']['priority'] = 2;
    $fields['first_name']['label'] = mb_strtoupper("prénom");
    $fields['first_name']['class'] = array('form-right');
    $fields['address_1']['priority'] = 110;
    $fields['address_1']['label'] = mb_strtoupper("adresse 1");
    $fields['address_2']['priority'] = 120;
    $fields['address_2']['label'] = mb_strtoupper("adresse 2");
    $fields['postcode']['label'] = mb_strtoupper("code postal");
    $fields['postcode']['priority'] = 130;
    $fields['postcode']['class'] = array('form-left-small');
    $fields['city']['label'] = mb_strtoupper("ville");
    $fields['city']['priority'] = 140;
    $fields['city']['class'] = array('form-right-big');
    $fields['country']['priority'] = 4;
    $fields['country']['label'] = mb_strtoupper("pays");
    $fields['country']['required'] = true;
    $fields['country']['class'] = array('form-right','address-field','update_totals_on_change');
    $fields['state']['priority'] = 120;
    $fields['state']['label'] = mb_strtoupper("téléphone");
    $fields['state']['required'] = true;
    $fields['state']['class'] = array('form-right');
return $fields;
    return $fields;
}

AND CSS

.woocommerce form .form-right,
.woocommerce form .form-left,
.woocommerce form .form-left-small,
.woocommerce form .form-right-big {
    display: inline-block;
}
.woocommerce form .form-right,
.woocommerce form .form-left {
    width: 48%
}
.woocommerce form .form-right,
.woocommerce form .form-big-right {
    margin-left: 2% !important;
}
.woocommerce form .form-left,
.woocommerce form .form-left-small {
    margin-right: 2% !important;
}
.woocommerce form .form-big-right {
    width: 63%;
}
.woocommerce form .form-left-small {
    width: 33%;
}
.woocommerce form .woocommerce-input-wrapper strong {
    height: 38px;
    line-height: 38px;
}

RESULT :

enter image description here

For WooCommerce > 4.0 you need to have a priority key, because it's using asort on the array just before printing it.

You can do this:

function order_fields( $fields ) {
    $i = 0;

    $order = array(
        "billing_email",
        "billing_customfield", <- this is your custom field
        "billing_company",
        "billing_cvr",
        "billing_ean",
        "billing_first_name",
        "billing_last_name",
        "billing_address_1",
        "billing_address_2",
        "billing_country",
        "billing_postcode",
        "billing_city",
        "billing_phone"
    );

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

    $fields["billing"] = $ordered_fields;

    return $fields;

}

add_filter( "woocommerce_checkout_fields", "order_fields" );
Related