Don’t Mess with the Magento 2 Checkout

Hello! Do you hate editing Magento Checkout? I know how you feel… πŸ˜€

The checkout in Magento 2 is built up from a series of Knockout JS components which are then rendered using the Knockout JS templating system. Magneto 2 defines each one of these components and their parent/child relationship in a large XML file which can be extended or overridden in your own theme or module.

First of all, it all starts in checkout_index_index.xml.

[Magento_Checkout_module_dir]/view/frontend/layout/checkout_index_index.xml

Create this file in your theme, and we can start:

[Magento_Checkout]/layout/checkout_index_index.xml

Example 1: Remove field from Shipping form

Define path to component which you are planing to remove and add this item as a child:
(in this example Fax field)

<item name="visible" xsi:type="boolean">false</item>
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Magento\Checkout\Block\Onepage" name="checkout.root" template="onepage.phtml" cacheable="false">
                <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">
                                                            <item name="shipping-address-fieldset" xsi:type="array">
                                                                <item name="children" xsi:type="array">
                                                                    <item name="fax" xsi:type="array">
                                                                        <item name="visible" xsi:type="boolean">false</item>
                                                                    </item>
                                                                </item>
                                                            </item>
                                                        ...

Clean the cache and the changes will be visible.

Example 2: Move component’s on Checkout

In this case, we will move Terms and Conditions from the default position (under payment method) to the end of Checkout.

Step 1: To show the item in the new place, we must first disable an item from the default position, follow XML tree and replace item:

<item name="before-place-order" xsi:type="array">
    ...
</item>

with:

<item name="before-place-order" xsi:type="array">
    <item name="componentDisabled" xsi:type="boolean">true</item>
</item>

Step 2: Re-add to your desired location, in this case on the end of Checkout:

<item name="after-place-agreements" xsi:type="array">
    <item name="component" xsi:type="string">uiComponent</item>
    <item name="displayArea" xsi:type="string">after-place-agreements</item>
    <item name="dataScope" xsi:type="string">before-place-order</item>
    <item name="provider" xsi:type="string">checkoutProvider</item>
    <item name="config" xsi:type="array">
        <item name="template" xsi:type="string">Magento_Checkout/payment/before-place-order</item>
    </item>
    <item name="children" xsi:type="array">
        <item name="agreementss" xsi:type="array">
            <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkout-agreements</item>
            <item name="sortOrder" xsi:type="string">100</item>
            <item name="displayArea" xsi:type="string">after-place-agreements</item>
            <item name="dataScope" xsi:type="string">checkoutAgreements</item>
            <item name="provider" xsi:type="string">checkoutProvider</item>
        </item>
    </item>
</item>

Step 3: Call this template where you need:
(in our example on the end of Checkout: “after-place-agreements”)

<!-- ko foreach: getRegion('after-place-agreements') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->

Example 3: Adding Custom block in Header

You’ll probably be in a position that the client wants more information in the Checkout header to increase the conversion rate, a sense of security sites, etc. Here’s how:

<referenceBlock name="checkout.header.wrapper">
    <container name="additional-custom-block-wrapper" label="additional-custom-block-wrapper" htmlTag="div" htmlClass="additional-custom-block-wrapper">
        <block class="Magento\Cms\Block\Block" name="additional-custom-block">
            <arguments>
                <argument name="block_id" xsi:type="string">additional-custom-block</argument>
            </arguments>
        </block>
    </container>
</referenceBlock>

Example 4: Adding Custom Footer to Checkout

If a want to highlight some specific things, methods of payment, information delivery, additional coupons, etc.
This is a sample of how to create a custom footer with CMS block or template file:

CMS Block

<referenceContainer name="page.bottom.container">
    <container name="additional-custom-footer-wrapper" label="additional-custom-footer-wrapper" htmlTag="div" htmlClass="additional-custom-footer-wrapper">
        <block class="Magento\Cms\Block\Block" name="additional-custom-footer">
            <arguments>
                <argument name="block_id" xsi:type="string">additional-custom-footer</argument>
            </arguments>
        </block>
    </container>
</referenceContainer>

Template

[Magento_Theme]/templates/checkout-footer.phtml
<referenceContainer name="page.bottom.container">
    <container name="additional-custom-footer-wrapper" label="additional-custom-footer-wrapper" htmlTag="div" htmlClass="additional-custom-footer-wrapper">
        <block class="Magento\Framework\View\Element\Template" name="additional-custom-footer" template="Magento_Theme::checkout-footer.phtml" />
    </container>
</referenceContainer>

If you’re going to need any help regarding your Magento development or Migration from Magento 1 to Magento 2 in particular, we would be more than happy to offer you insights and various solutions. Happy coding!


About Matej Djakovic

Frontend Developer

Matej is a Frontend Developer who is passionate about Wordpress, Symfony 2 and Magento. He is also enthusiastic about sports and spends some of his free time for inline roller skating.

Read more posts by Matej / Visit Matej's profile

17 comments

  1. Hey Matej

    Awesome article. Thank you for sharing!

    I am trying to bring the shipping and billing information into one step, so effectively there is a single view for the checkout (rather than the default two-step process. How would you suggest I do this please? Any insight would be greatly appreciated πŸ˜„

    Many thanks
    Steve

  2. Is there something like a copy method? Instead of readding everything by copy & paste in the checkout?

  3. Hi, In example 2, step 2 what exactly does “end of checkout” means? After which node am I suppose to place the new code?

    1. Hi Reya, place in “checkout” node in “children” after ” <item name=”steps” xsi:type=”array”>…</step> “ and step 3 add in onepage.html

      Good luck!

  4. Hi Matej Djakovic

    How can I remove the shipping methods step from shipping and add as a separate step in checkout flow.

    Thanks.

  5. Hi!
    How is possible to remove some tooltips from checkout?
    I tried so many possible solutions but none worked for me…

    1. Hi Francis,
      i think the best way to do this through CSS, i tried in several ways, but considering all the complications with Checkout, best through CSS.

      Good luck! πŸ˜‰

  6. How to add validation to the shipping address fields in checkout page? For ex: UPS Address validation

  7. Hello,
    I am having a serious issue. I need a help. I want to add new shipping method i.e., In-store. If it is selected then customer can choose stores which is listed in admin section and goto next. When In-store is selscted then no need to add shipping address and store adderss will be added as a shipping address. I have tried using custom js and ajax and I am facing huge page loading issue. What is the best way to do so and how?

  8. Hi!

    First off all great article, easy and understandable :).
    Second, now i’m searching for a more indept article about the checkout.
    Cause i want to build an address autocompleter in it, but can’t figure realy out how i can make use of the observable objects of the shipping address form input’s, so that when a few fields are filled in i can do a request with JS to auto complete the address and make some fields readonly. Any “simple” example’s about it?

    Kindly regards

    1. Hi Pascal,
      at start you need add your custom JS on Checkout, add in head of checkout_index_index.xml,
      for make read only field need create new template for field (see here) and add attribute to field “disabled”

      Good luck! πŸ™‚

  9. hi,

    in my checkout_index_index.xml i have added

    true

    but the placeholder button is always present on payment list checkout.

    What is the problem?

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>.