Magento2 Checkout – Create Plugin LayoutProcessor::process vs Override checkout_index_index.xml

checkoutlayoutmagento2xml

To add a custom field, I can create a plugin and it will add input on the checkout.

1) Create plugin LayoutProcessor::process

Exapmle :

Namespace/Module/etc/frontend/di.xml

<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="add_custom_field_checkout_form" type="Namespace\Module\Model\Plugin\Checkout\LayoutProcessor" sortOrder="100"/>
    </type>
</config>

Namespace/Module/Model/Plugin/Checkout/LayoutProcessor.php

<?php
namespace Namespace\Module\Model\Plugin\Checkout;
class LayoutProcessor
{
    public function afterProcess(
    \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
    array $jsLayout
    ) {
        $jsLayout['components']['checkout']['children']['steps']
        ['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']
        ['children']['custom_field'] = [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                'customScope' => 'shippingAddress.custom_attributes',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/input',
                'options' => [],
                'id' => 'custom-field'
            ],
            'dataScope' => 'shippingAddress.custom_attributes.custom_field',
            'label' => 'Custom Field',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => [],
            'sortOrder' => 250,
            'id' => 'custom-field'
        ];

        return $jsLayout;
    }

}

2) Override checkout_index_index.xml

But there is another way, when I can expand checkout_index_index.xml.
For example, I'll add a checkbox :

Namespace/Module/view/frontend/layout/checkout_index_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <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">
                                        <!-- Modifying an existing step-->
                                        <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="before-form" xsi:type="array">
                                                            <item name="children" xsi:type="array">
                                                                <item name="newsletter" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Namespace_Module/js/view/newsletter</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

Next, I will create these files :

Namespace/Module/view/frontend/web/js/view/newsletter.js
Namespace/Module/view/frontend/web/template/newsletter.html

And get the checkbox on the form.

Question : Tell me please, in order to change the checkout, when should I create plugin LayoutProcessor::process and when to override checkout_index_index.xml?

Best Answer

XML Checkout. Should think about XML first.

1) A standard practice

Most of the developer will take a look the XML first to check the XML layout.

2) Maintenance

If you're familiar with checkout XML, you will see that it's easy to change. On the other hand, LayoutProcessor::process() will be "messy" if there are one more changes from different extensions.

When do we need to use LayoutProcessor::process() plugin?

1) Complex logic

It's hard to say in this case. But for example:

\Magento\Checkout\Block\Checkout\LayoutProcessor::process($jsLayout)

......
['payment']['children'] = $this->processPaymentChildrenComponents(
                $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
                ['payment']['children'],
                $elements
            );
......

We need to assign the billing info to each payment. As we can see, it's impossible to use XML.

2) Remove component completely

We can use XML to disable a component, but component still is rendered. We can remove this component completely.

XML:

<item name="%the_component_to_be_disabled%" xsi:type="array">
    <item name="config" xsi:type="array">
        <item name="componentDisabled" xsi:type="boolean">true</item>
    </item>
</item>

LayoutProcessor::process()

unset($jsLayout['components']['checkout']['children']['steps'][%path_to_target_node%]); //%path_to_target_node% is the path to the component's node in checkout_index_index.xml
return $jsLayout;

3) Can do what XML cannot do...

Don't need to explain more here.

Related Topic