Reorder input fields on Shipping and Billing step in Magento 2

Reorder input fields on Shipping and Billing step in Magento 2

With time we are becoming more and more familiar with Magento 2 Checkout. And we are trying to build our knowledge furthermore. Hopefully, this article will help you in that process. With this article, we’ll learn how to change inputs fields ordering on the Checkout page.

If you ever tested Magento 2 you are familiar with default Magento 2 Checkout and the default fields sort ordering. If you wish to want to recall it, check this screenshot:

Default Magento 2 input ordering

This ordering is totally understandable for the addresses in USA or some other countries where State/Provinces is important and required field. But in the most European countries State/Province field isn’t nessery. Here, majority of EU customers expect some other fields, for example here Post code or Country have higher priority.

Keeping that in mind we wish to change default Magento Checkout fields sort ordering to fit our needs. So, our goal is to achieve this:

Our Magento 2 checkout inputs ordering

If you have a different idea, that is absolutely fine, follow this article and change the fields ordering value as you wish.

Also we wish to have consistency, thought all Checkout steps so we will reorder input fields on Shipping and Billing step.

Shipping step

Re-ordering fields on the Shipping step is a simple task, we just need to know sort order value of relevant fields and few xml Magento 2 specific commands.

First thing, we need to have our own checkout_index_index layout override. If you don’t have it, please create new checkout_index_index xml file so that we can manipulate Checkout layout on proper Magento way. The file need to be located on this path:

/app/design/frontend/Vendor/themeName/Magento_Checkout/layout/checkout_index_index.xml

New layout file need to have clearly structured tree in order to target correct elements Checkout UI components, like this:

<referenceBlock name="checkout.root">
<arguments>
    <argument name="jsLayout" xsi:type="array">
        <item name="components" xsi:type="array">
            <item name="checkout" xsi:type="array">
                <item name="children" xsi:type="array">
                    <item name="steps" xsi:type="array">
                        <item name="children" xsi:type="array">
                            <item name="shipping-step" xsi:type="array">
                                <item name="children" xsi:type="array">
                                    <item name="shippingAddress" xsi:type="array">
                                        <item name="children" xsi:type="array">
                                            <!-- The name of the form the field belongs to -->
                                            <item name="shipping-address-fieldset" xsi:type="array">
                                                <item name="children" xsi:type="array">
 
                    <!— Start: Important part —>
 
                                                    <item name="postcode" xsi:type="array">
                                                        <item name="sortOrder" xsi:type="string">71</item>
                                                    </item>
 
                                                    <item name="country_id" xsi:type="array">
                                                        <item name="sortOrder" xsi:type="string">81</item>
                                                    </item>
                    <!— End: Important part: —>
 
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </item>
            </item>
        </item>
    </argument>
</arguments>
</referenceBlock>

There is a lot of nesting and lot of children elements. But under the shippingAddress item we are targeting two children elements which represent the input fields. If you take a look closely, you can notice that we are trying to target:

  • Post code field (postcode)
  • Country filed (country_id)

In order to change the position of this elements (postcode and country) we need to update sortOrdering value with value which will fit our idea for better sort ordering. By default postcode have sortOrder value of 110 and country_id have value of 115. And we have update them with 71 and 81, in that case targeted fields will well to our new layout.

Clear your Magento cache. Reload the Checkout page and you will notice the changes.

Also we need to point out that XML layout update will affect also the Checkout address popup which will be visible when registered customer wish to add new address with the already existing address on the first checkout step.

Now let us adjust Billing step.

Billing step

Altering billing step request different approach then the Shipping step. Reason for it that Billing step is built on the dynamic UI components. Currently, the most important thing to know here is that on the Billing step each payment methods using different billing address form (different components for each payment method). So having that in mind we need to apply layout changes for all payment methods that we are using on the Checkout. But for the purpose of this article, we will cover just the Check / Money payment method.

We will do this by extending default Magento Layout Processor Interface for the Billing step. This will require a bit of PHP backend adjustments. But considering the level of work necessary, it will not be too complicated to do it. Please extend LayoutProcessorInterface by creating new PHP class file under Checkout, Block directory:

/app/code/Vendor/Checkout/Block/LayoutProcessor.php


Override of ClassLayoutProcessor

And for our starting point will use simple function check:

namespace Inchoo\Checkout\Block;
 
use Magento\Checkout\Block\Checkout\LayoutProcessorInterface;
 
class LayoutProcessor implements LayoutProcessorInterface
{
    public function process($jsLayout)
    {
        return $jsLayout;
    }
}

Also we need to create di.xml for the config so that Magento understand Layout processor changes. XML file will contain this code:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Checkout\Block\Onepage">
        <arguments>
            <argument name="layoutProcessors" xsi:type="array">
                <item name="checkoutFieldsReorder" xsi:type="object">Inchoo\Checkout\Block\LayoutProcessor</item>
            </argument>
        </arguments>
    </type>
</config>

We need to ensure that we are targeting correct UI components on the billing step. In order to that, do the inspection of JSON object which Magento knockout give us on the frontend. You can do it via your IDE or some JSON online editor. Find sortOrder values in Checkout JSON for the elements which you wish to reposition. Following the JSON tree we will declare same path to the $jsLayout array. So basically, we will do this:

namespace Inchoo\Checkout\Block;
 
use Magento\Checkout\Block\Checkout\LayoutProcessorInterface;
 
class LayoutProcessor implements LayoutProcessorInterface
{
    /**
     * Reposition postcode to be above city input, and country drop down to be above region
     * 
     * @param array $jsLayout
     * @return array
     */
    public function process($jsLayout)
    {
        $jsLayout['components']['checkout']['children']['steps']['children']
        ['billing-step']['children']['payment']['children']
        ['payments-list']['children']['checkmo-form']['children']
        ['form-fields']['children']['postcode']['sortOrder'] = 71;
 
        $jsLayout['components']['checkout']['children']['steps']['children']
        ['billing-step']['children']['payment']['children']
        ['payments-list']['children']['checkmo-form']['children']
        ['form-fields']['children']['country_id']['sortOrder'] = 81;
 
        return $jsLayout;
    }
}

Clear cache and reload the page. You will see the changes.
If you wish to change layout for some other method, feel free to do it. You just need to replace ['checkmo-form'] with your payment method. But make sure which method you are using on the Checkout. At least check your JSON object and what forms are available under your payment-list item. Reason for this is that sometimes payment-list can look like this:
Checkout JSON - payment list

So it is difficult to guess which form we need to target. Find what you need to target and good luck.

That is all guys.

If you need some professional assistance with your Magento theme please feel free to contact us for Technical audit.

Regards.

Related Inchoo Services

You made it all the way down here so you must have enjoyed this post! You may also like:

3 best open-source eCommerce platforms in 2021 Zrinka Antolovic
Zrinka Antolovic, | 8

3 best open-source eCommerce platforms in 2021

More/Less functionality in Magento2 Danijel Vrgoc
, | 6

More/Less functionality in Magento2

Creating a shipping method in Magento 2 Domagoj Potkoc
Domagoj Potkoc, | 26

Creating a shipping method in Magento 2

14 comments

  1. Calling this “simple” is a bit of a stretch. M2 is so effing over engineered that even simple tasks turn out to be a horror show.

    Oh and good luck figuring out how you did it 6 months later.

  2. Thank you.
    For billing address, I have used after plugin.
    Magento\Checkout\Block\Onepage::getJsLayout()

  3. Hello
    why didn’t you use plugin with arround method to overwrite the core class instead?
    thanks

  4. Nice example. I have a question though. The first approach (where you extend checkout_index_index.xml ) seems to be working with the billing step as well. However from what you wrote I gather that for the billing step the second approach (where you add a layout processor) is necessary. Aren’t these two approaches equivalent? What’s the difference?

  5. Hello Mldan,

    I tested Shipping step but it didn’t work for me.
    I followed your tutorial. I created in this directory app/design/frontend/Inchoo/InchooTheme/Magento_Checkout/layout, the file checkout_index_index.xml.
    I put the content that you described above.
    I clear the cache with this command line: bin/magento cache:clean
    Thanks for you help

  6. Hello ,it is an awesome post.Thank you for sharing! But I have some difficult understand the following .

    We need to ensure that we are targeting correct UI components on the billing step. In order to that, do the inspection of JSON object which Magento knockout give us on the frontend. You can do it via your IDE or some JSON online editor. Find sortOrder values in Checkout JSON for the elements which you wish to reposition.

    I just to want to know how to find the ‘ JSON object ‘, Could you explain the process of finding that object in detail? Thank you ! It is so kind of you!

    1. Hi Dan,

      that part is easy, just open the Magento 2 checkout page, right click, select the View Page Source. And search for

      {
                  "#checkout": {

      then, copy whole JS code inside SCRIPT tag and past all that to JSON format tool.

      Kind regards.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.