18

on the onepage checkout I need to reorder the billing address before the shipping address. in fact the logic should be the other way around than it is now. if the shipping address differs from the billing address you should be able to edit it. now you can edit the billing address if it differs from the shipping address. also the billing address should appear on the same "page" as the shipping address. currently step 1 in the magento checkout steps.

how would I do this? maybe there is a plugin for this but I couldn't find one yet.

I attached a screenshot of a german shop doing it like this:

enter image description here

I found the .html template file for the billing form and it seems this is the place where it ends up in the checkout_index_index.xml:

<item name="billing-step" xsi:type="array">
    <item name="component" xsi:type="string">uiComponent</item>
    <item name="sortOrder" xsi:type="string">2</item>
    <item name="children" xsi:type="array">
        <item name="payment" xsi:type="array">
            <item name="component" xsi:type="string">Magento_Checkout/js/view/payment</item>
            <item name="config" xsi:type="array">
                <item name="title" xsi:type="string" translate="true">Payment</item>
            </item>
            <item name="children" xsi:type="array">
                <!-- ... -->
                <!-- merge your payment methods here -->
                <item name="afterMethods" xsi:type="array">
                    <item name="component" xsi:type="string">uiComponent</item>
                    <item name="displayArea" xsi:type="string">afterMethods</item>
                    <item name="children" xsi:type="array">
                        <!-- merge additional data after payment methods here -->

<!-- I think here the billing form ends up -->

                    </item>
                </item>
            </item>
        </item>
    </item>
</item>

But it's not specifically placed here and I can't seem to find another place where it is injected to that place.

8
  • 2
    The billing address form is added in the file Magento/Checkout/Block/Checkout/LayoutProcessor.php. Commented Apr 12, 2017 at 12:27
  • Yep that's it. There I managed to reorder at least. Still have to switch the address logic though.
    – steros
    Commented Apr 12, 2017 at 14:27
  • you have using custom checkout?
    – Amit Bera
    Commented Apr 16, 2017 at 14:31
  • Need to override Magento\Checkout\Block\Checkout\LayoutProcessor & change position as I am thinking. Not sure
    – Jackson
    Commented Apr 17, 2017 at 9:54
  • 1
    @AnkitShah That won't work as I just need to move the billing address not the whole billing step. Also as Aaron pointed out the first step to do it is write a module that overwrites LayoutProcessor. I already did that successfully but still the logic of choosing the billing address being the same as the shipping address is not correct. And additionally I'm not sure if the whole process will work. At least I can go on in the checkout but I'm not sure about side-effects so far.
    – steros
    Commented Apr 19, 2017 at 7:46

2 Answers 2

12

As Aaron pointed out the form is added in Magento/Checkout/Block/Checkout/LayoutProcessor.php. With this information I developed a module with an after plugin that hooks onto that processor:

app/code/<vendor>/<module>/Model/Checkout/LayoutProcessorPlugin.php

<?php

namespace <vendor>\ReorderBillingForm\Model\Checkout;

class LayoutProcessorPlugin
{

    /**
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */

    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        array $jsLayout
    )
    {
        // get billing address form at billing step
        $billingAddressForm = $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['children']['afterMethods']['children']['billing-address-form'];

        // move address form to shipping step
        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['billing-address-form'] = $billingAddressForm;

        // remove form from billing step
        unset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['children']['afterMethods']['children']['billing-address-form']);

        return $jsLayout;
    }
}

app/code/<vendor>/<module>/etc/module.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="<vendor>_<module>" setup_version="1.0.0"/>
</config>

app/code/<vendor>/<module>/etc/di.xml

<?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\Checkout\LayoutProcessor">
        <plugin name="reorder-billing-form"
                type="<vendor>\<module>\Model\Checkout\LayoutProcessorPlugin" sortOrder="<yourOrder>"/>
    </type>
</config>

app/code/<vendor>/<module>/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '<vendor>_<module>',
    __DIR__
);

This successfully reorders the billing address form (and hopefully saves some headaches for other people). But there is still work needed on the javascript(?) that handles the billing address is the same as shipping address mechanism. As this still works the "standard" way.

Additional info:

I saw that in the backend if you create a new order the layout is exactly as wanted. The billing form is "before" the shipping form and the logic is the other way around too. If I can find the time I think it might be beneficial to look at the code there. Maybe it is possible to use it in frontend too.

12
  • Shouldn't the namespace be namespace <vendor>\ReorderBillingForm\Block\Checkout; ? Commented Jun 1, 2017 at 14:01
  • 2
    Not sure. I ran into caching problems (yet again) it seems. Sometimes it wouldn't work, sometimes it did. I rewrote the module and now it works all the time. It was important to use aroundProcess. I updated my post.
    – steros
    Commented Jun 2, 2017 at 6:47
  • Thanks for updating your answer but i get the following error Notice: Undefined index: billing-address-form in LayoutProcessorPlugin.php:20 Commented Jun 2, 2017 at 8:06
  • Hmm strange, I don't get that. But you can check how the $jsLayout is structured by debugging. I don't have a running instance currently. If I setup another one I'll try to find out what might be the issue.
    – steros
    Commented Jun 2, 2017 at 15:41
  • Did you already update the answer? you are still using afterProcess, not around Process @DarsVaeda We are using your solution but have the Billign Address on the Payment Step still appearing
    – Alex
    Commented Aug 5, 2017 at 10:06
1

The error Undefined index: billing-address-form in LayoutProcessorPlugin.php occurs when you have the checkout property "Display Billing Address On" set to "Payment Method" instead of "Payment Page".

Fix with:

UPDATE core_config_data SET VALUE = 1 WHERE path = 'checkout/options/display_billing_address_on';

I would have preferred to add this as a comment to DarsVaedas post (see above), but I don't seem to have the permission …

1
  • thanks @jaybong for adding the sql statement to fix this!
    – digijay
    Commented Mar 26, 2019 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.