Woocommerce - Overriding Billing State and Post Code on Existing Checkout Fields

WooCommerce - Overriding billing state and post code on existing checkout fields

This is the complete way for billing state and billing post code override, keeping the billing selector with options.

Here is the code the fully functional and tested code:

  1. Unsetting billing state and post code checkout fields
add_filter( 'woocommerce_checkout_fields' , 'partial_unsetting_checkout_fields' );
function partial_unsetting_checkout_fields( $fields ) {
unset($fields['billing']['billing_state']);
unset($fields['billing']['billing_postcode']);

return $fields;
}

  1. Reinserting custom billing state and post code checkout fields
add_filter( 'woocommerce_default_address_fields' , 'art_override_default_address_fields' );
function art_override_default_address_fields( $address_fields ) {

// @ for state
$address_fields['billing_state']['type'] = 'select';
$address_fields['billing_state']['class'] = array('form-row-wide');
$address_fields['billing_state']['required'] = true;
$address_fields['billing_state']['label'] = __('State', 'my_theme_slug');
$address_fields['billing_state']['placeholder'] = __('Enter state', 'my_theme_slug');
$address_fields['billing_state']['default'] ='Choice 1';
$address_fields['billing_state']['options'] = array(
'option_1' => 'Choice 1',
'option_2' => 'Choice 2',
'option_3' => 'Choice 3'
);

// @ for postcode
$address_fields['billing_postcode']['type'] = 'text';
$address_fields['billing_postcode']['class'] = array('form-row-wide');
$address_fields['billing_postcode']['required'] = true;
$address_fields['billing_postcode']['label'] = __('Postcode', 'my_theme_slug');
$address_fields['billing_postcode']['placeholder'] = __('Enter your postcode', 'my_theme_slug');

return $address_fields;
}

Naturally this goes on function.php file of your active child theme or theme

Official reference: WooThemes - Customizing checkout fields using actions and filters


Note concerning the 'class' property

There is 2 ways to handle it:

  • The field is alone in one line (width 100%), you use: 'form-row-wide'
  • There is 2 fields side by side on the same line, you use:

    • 'form-row-first' for the first field
    • 'form-row-last' for the second field

How to change Billing address field label in WooCommerce

In specific cases you need to use the woocommerce_default_address_fields filter. This filter is applied to all billing and shipping default fields:

'country', 'first_name', 'last_name', 'company', 'address_1', 'address_2', 'city', 'state' or 'postcode'.

Here we only use 'city' and 'postcode' as in your code:

add_filter( 'woocommerce_default_address_fields' , 'override_default_address_fields' );
function override_default_address_fields( $address_fields ) {

// @ for city
$address_fields['city']['class'] = array('form-row-first');
$address_fields['city']['label'] = __('Province', 'woocommerce');

// @ for postcode
$address_fields['postcode']['label'] = __('Zipcode', 'woocommerce');

return $address_fields;
}

This is tested and working.

This code snippet goes on function.php file of your active child theme or theme

References:

  • Official WooThemes - Customizing checkout fields using actions and filters
  • WooCommerce - Overriding billing state and post code on existing checkout fields

Checkout fields - Make billing_address_2 above billing_address_1

Update (related to your comment)…

Here you have an addition that removes "Address" text label from Address1 field and set it to Address2 field, making also that field (optionally) required and changing a little bit the place holder… I have also another solution (see below after the code).

Here is the code:

add_filter( 'woocommerce_checkout_fields', 'custom_billing_fields_order' );
function custom_billing_fields_order( $fields ) {

// 1. Customizing address_1 and address_2 fields
$fields['billing']['billing_address_1']['label'] = ''; // Removing the label from Adress1
$fields['billing']['billing_address_2']['label'] = __('Address', 'theme_domain');
$fields['billing']['billing_address_2']['required'] = true; // Making Address 2 field required
$fields['billing']['billing_address_2']['placeholder'] = __('Apartment, suite, unit etc...', 'woocommerce');

// 2. Custom ordering the billing fields array (toggling address_1 with address_2)
$custom_fields_order = array(
'billing_first_name', 'billing_last_name',
'billing_company',
'billing_email', 'billing_phone',
'billing_country',
'billing_address_2', 'billing_address_1', ## <== HERE, changed order
'billing_postcode', 'billing_city'
);

foreach($custom_fields_order as $field)
$new_ordered_fields[$field] = $fields['billing'][$field];

// Replacing original fields order by the custom one
$fields['billing'] = $new_ordered_fields;

// Returning Checkout customized billing fields order
return $fields;
}

Instead of toggling that 2 fields, you could invert the fields placeholders and add make (optionally) required the field Address2, so you will not need to reorder the fields. You can do it this way:

add_filter( 'woocommerce_checkout_fields', 'custom_billing_fields_placeholders' );
function custom_billing_fields_placeholders( $fields ) {

// 1. Customizing address_1 and address_2 fields
$fields['billing']['billing_address_1']['placeholder'] = __('Apartment, suite, unit etc...', 'woocommerce');
$fields['billing']['billing_address_2']['required'] = true; // Making Address 2 field required
$fields['billing']['billing_address_2']['placeholder'] = __('Street address', 'woocommerce');

// Returning Checkout customized billing fields
return $fields;
}

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

Code is tested and works.


Related answers: Checkout fields: Hiding and showing existing fields

Official documentation: Customizing checkout fields using actions and filters

Sorting priority for specific Woocommerce checkout fields depending on country

Using available filter hook you can make that change without overriding core files…

The first change is made with this hook (for "IT" country code):

add_filter('woocommerce_get_country_locale', 'custom__country_locale', 30, 1 );
function wps_select_order_meta_keys( $locale ) {
$locale['IT']['postcode']['priority'] = 91;
return $locale;
}

For the second change you need also to change the class. It's the same code that you already have in the answer to your other question, but without this line to be removed:

if( ! is_account_page() ) return $fields;

The code is:

add_filter(  'woocommerce_billing_fields', 'custom_billing_fields', 20, 1 );
function custom_billing_fields( $fields ) {

## ---- 1. Sort billing email and phone fields ---- ##

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

return $fields;
}

So if you remove if( ! is_account_page() ) return $fields; from the code in my other answer, it will work also on checkout page (as as already indicated)…

So you can use (for both account and checkout pages):

add_filter(  'woocommerce_default_address_fields', 'custom_default_address_fields', 20, 1 );
function custom_default_address_fields( $fields ) {

## ---- 1. Remove 'address_2' field ---- ##

unset($fields['address_2']);

## ---- 2. Sort Address fields ---- ##

// Set the order (sorting fields) in the array below
$sorted_fields = array('first_name','last_name','company','address_1','country','postcode','city','state');

$new_fields = array();
$priority = 0;

// Reordering billing and shipping fields
foreach($sorted_fields as $key_field){
$priority += 10;

if( $key_field == 'company' )
$priority += 20; // keep space for email and phone fields

$new_fields[$key_field] = $fields[$key_field];
$new_fields[$key_field]['priority'] = $priority;
}
return $new_fields;
}

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

Reordering checkout fields in WooCommerce 3

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:

  • Official: Customizing checkout fields using actions and filters
  • How to reorder billing fields in WooCommerce Checkout template?

Displaying custom table values in WooCommerce checkout form

We are going to first unset the field type of company, and then to change it to a type 'select' (selector). Then we will maque a query to get all options key/values from your custom database table (Let's say is called 'wp_companies'):

(ONLY FOR TESTING) NO database query here (with 3 options for companies):

add_filter( 'woocommerce_default_address_fields' , 'set_custom_company_checkout_field' );
function set_custom_company_checkout_field( $address_fields ) {

unset($fields['company']['type']);

$address_fields['company']['type'] = 'select';
$address_fields['company']['options'] = array(
'option_1' => 'Company 1',
'option_2' => 'Company 2',
'option_3' => 'Company 3'
);
// (optional)
// $address_fields['company']['default'] = 'Company 1';

return $address_fields;
}

Paste this code in function.php file located in your active child theme (or theme).

This code is tested and works…


THE REAL CODE: Making the query from database custom table (to be adapted):

add_filter( 'woocommerce_default_address_fields' , 'set_custom_company_checkout_field' );
function set_custom_company_checkout_field( $address_fields ) {

// Unset company field type
unset($fields['company']['type']);

global $wpdb;
$select_options = array();

// @@@ you will need to replace names table and columns and adapt this !!!
$query = "SELECT id, company FROM table";
$companies_name = $wpdb->get_results($query);

// Storing object $company_name keys/values in $select_options array
foreach ( $companies_name as $company_name )
{
$key = 'option_'. $company_name->ID;
$value = $company_name->custom_column_value;
$select_options[$key] = $value ;
}

$address_fields['company']['type'] = 'select';
$address_fields['company']['options'] = $select_options;
// (optional)
// $address_fields['company']['default'] = $select_options['option_1'];

return $address_fields;
}

Paste this code in function.php file located in your active child theme (or theme).

References:

  • WooThemes - Customizing checkout fields using actions and filters
  • WooCommerce - Overriding billing state and post code on existing checkout fields


Related Topics



Leave a reply



Submit