0

My goal is to overwrite the billing-address.js component so that I can add some custom bindings to a certain element on the billing-information.html template.

I figured out that the module-checkout/block/checkout/LayoutProcessor.php processPaymentConfiguration method is responsible in initializing the billing-address js component.

module-checkout/block/checkout/LayoutProcessor.php

 /**
     * Inject billing address component into every payment component
     *
     * @param array $configuration list of payment components
     * @param array $elements attributes that must be displayed in address form
     * @return array
     */
    private function processPaymentConfiguration(array &$configuration, array $elements)
    {
        $output = [];
        foreach ($configuration as $paymentGroup => $groupConfig) {
            foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) {
                if (empty($paymentComponent['isBillingAddressRequired'])) {
                    continue;
                }
                $output[$paymentCode . '-form'] = [
                    'component' => 'Magento_Checkout/js/view/billing-address',
                    'displayArea' => 'billing-address-form-' . $paymentCode,
                    'provider' => 'checkoutProvider',
                    'deps' => 'checkoutProvider',
                    'dataScopePrefix' => 'billingAddress' . $paymentCode,
                    'sortOrder' => 1,
                    'children' => [
                        'form-fields' => [
                            'component' => 'uiComponent',
                            'displayArea' => 'additional-fieldsets',
                            'children' => $this->merger->merge(
                                $elements,
                                'checkoutProvider',
                                'billingAddress' . $paymentCode,
                                [
                                    'country_id' => [
                                        'sortOrder' => 115,
                                    ],
                                    'region' => [
                                        'visible' => false,
                                    ],
                                    'region_id' => [
                                        'component' => 'Magento_Ui/js/form/element/region',
                                        'config' => [
                                            'template' => 'ui/form/field',
                                            'elementTmpl' => 'ui/form/element/select',
                                            'customEntry' => 'billingAddress' . $paymentCode . '.region',
                                        ],
                                        'validation' => [
                                            'validate-select' => true,
                                        ],
                                        'filterBy' => [
                                            'target' => '${ $.provider }:${ $.parentScope }.country_id',
                                            'field' => 'country_id',
                                        ],
                                    ],
                                    'postcode' => [
                                        'component' => 'Magento_Ui/js/form/element/post-code',
                                        'validation' => [
                                            'required-entry' => true,
                                        ],
                                    ],
                                    'company' => [
                                        'validation' => [
                                            'min_text_length' => 0,
                                        ],
                                    ],
                                    'fax' => [
                                        'validation' => [
                                            'min_text_length' => 0,
                                        ],
                                    ],
                                    'telephone' => [
                                        'config' => [
                                            'tooltip' => [
                                                'description' => 'For delivery questions.',
                                            ],
                                        ],
                                    ],
                                ]
                            ),
                        ],
                    ],
                ];
            }
            unset($configuration[$paymentGroup]['methods']);
        }

        return $output;
    }

My intention is to overwrite the processPaymentConfiguration method and redefine the component to point to the component in my custom module. Something along the lines of...

How I want to modify the processPaymentConfiguration method

/**
     * Inject billing address component into every payment component
     *
     * @param array $configuration list of payment components
     * @param array $elements attributes that must be displayed in address form
     * @return array
     */
    private function processPaymentConfiguration(array &$configuration, array $elements)
    {
        $output = [];
        foreach ($configuration as $paymentGroup => $groupConfig) {
            foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) {
                if (empty($paymentComponent['isBillingAddressRequired'])) {
                    continue;
                }
                $output[$paymentCode . '-form'] = [
                    'component' => 'MilkJarCookies_OrderDeliveryDate/js/view/billing-address',
                    'displayArea' => 'billing-address-form-' . $paymentCode,
                    'provider' => 'checkoutProvider',
                    'deps' => 'checkoutProvider',
                    'dataScopePrefix' => 'billingAddress' . $paymentCode,
                    'sortOrder' => 1,
                    'children' => [
                        'form-fields' => [
                            'component' => 'uiComponent',
                            'displayArea' => 'additional-fieldsets',
                            'children' => $this->merger->merge(
                                $elements,
                                'checkoutProvider',
                                'billingAddress' . $paymentCode,
                                [
                                    'country_id' => [
                                        'sortOrder' => 115,
                                    ],
                                    'region' => [
                                        'visible' => false,
                                    ],
                                    'region_id' => [
                                        'component' => 'Magento_Ui/js/form/element/region',
                                        'config' => [
                                            'template' => 'ui/form/field',
                                            'elementTmpl' => 'ui/form/element/select',
                                            'customEntry' => 'billingAddress' . $paymentCode . '.region',
                                        ],
                                        'validation' => [
                                            'validate-select' => true,
                                        ],
                                        'filterBy' => [
                                            'target' => '${ $.provider }:${ $.parentScope }.country_id',
                                            'field' => 'country_id',
                                        ],
                                    ],
                                    'postcode' => [
                                        'component' => 'Magento_Ui/js/form/element/post-code',
                                        'validation' => [
                                            'required-entry' => true,
                                        ],
                                    ],
                                    'company' => [
                                        'validation' => [
                                            'min_text_length' => 0,
                                        ],
                                    ],
                                    'fax' => [
                                        'validation' => [
                                            'min_text_length' => 0,
                                        ],
                                    ],
                                    'telephone' => [
                                        'config' => [
                                            'tooltip' => [
                                                'description' => 'For delivery questions.',
                                            ],
                                        ],
                                    ],
                                ]
                            ),
                        ],
                    ],
                ];
            }
            unset($configuration[$paymentGroup]['methods']);
        }

        return $output;
    }

Here is the catch... I have already created a LayoutProcessorPlugin since I needed to introduce new fields into the checkout shipping page.

Contents of my di.xml file

<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="order-delivery-date"
                type="MilkJarCookies\OrderDeliveryDate\Block\Plugin\Checkout\LayoutProcessorPlugin" sortOrder="10"/>
    </type>
</config>

The LayoutProcessorPlugin.php below adds a date, time slot and special instructions fields.

MilkJarCookies/OrderDeliveryDate/Block/Plugin/Checkout/LayoutProcessorPlugin.php

namespace MilkJarCookies\OrderDeliveryDate\Block\Plugin\Checkout;

use Bss\OrderDeliveryDate\Block\Plugin\Checkout\LayoutProcessorPlugin as BaseLayoutProcessorPlugin;

class LayoutProcessorPlugin extends BaseLayoutProcessorPlugin
{
    protected $_helper;
    const DELIVERY_FORM_DISPLAY_AT_SHIPPING_ADDRESS = 0;
    const DELIVERY_FORM_DISPLAY_AT_SHIPPING_METHOD = 1;
    const DELIVERY_FORM_DISPLAY_AT_REVIEW_PAYMENTS = 2;

    public function __construct(
        \MilkJarCookies\OrderDeliveryDate\Helper\Data $helper
    ) {
        $this->_helper = $helper;
    }

    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        array  $jsLayout
    ) {
        $container = null;
        if(!$this->_helper->isEnabled()) return $jsLayout;
        if($this->_helper->getDisplayAt() == self::DELIVERY_FORM_DISPLAY_AT_SHIPPING_ADDRESS) {
            $container = 'shipping-address-fieldset';
        } elseif($this->_helper->getDisplayAt() == self::DELIVERY_FORM_DISPLAY_AT_SHIPPING_METHOD) {
            $container = 'before-shipping-method-form';
        }
        // before place order
        if($this->_helper->getDisplayAt() == self::DELIVERY_FORM_DISPLAY_AT_REVIEW_PAYMENTS){
            $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
            ['payment']['children']['payments-list']['children']['before-place-order']['children']['shipping_arrival_date'] = [
                'component' => 'MilkJarCookies_OrderDeliveryDate/js/form/element/abstract',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'MilkJarCookies_OrderDeliveryDate/form/element/date',
                    'options' => [],
                    // 'disabled' => true,
                    'id' => 'shipping-arrival-date',
                    'class' => 'test'
                ],
                'dataScope' => 'shippingAddress.shipping_arrival_date',
                'label' => 'Delivery Date',
                'provider' => 'checkoutProvider',
                'visible' => true,
                'validation' => [],
                'sortOrder' => 200,
                'id' => 'shipping-arrival-date'
            ];
        }else{
            $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
            ['shippingAddress']['children'][$container]['children']['shipping_arrival_date'] = [
                'component' => 'MilkJarCookies_OrderDeliveryDate/js/form/element/abstract',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'MilkJarCookies_OrderDeliveryDate/form/element/date',
                    'options' => [],
                    // 'disabled' => true,
                    'id' => 'shipping-arrival-date'
                ],
                'dataScope' => 'shippingAddress.shipping_arrival_date',
                'label' => 'Delivery Date',
                'provider' => 'checkoutProvider',
                'visible' => true,
                'validation' => [],
                'sortOrder' => 200,
                'id' => 'shipping-arrival-date'
            ];
        }

        if($this->_helper->getTimeSlot()){
            // before place order
            if($this->_helper->getDisplayAt() == self::DELIVERY_FORM_DISPLAY_AT_REVIEW_PAYMENTS){
                $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
                ['payment']['children']['payments-list']['children']['before-place-order']['children']['delivery_time_slot'] = [
                    'component' => 'MilkJarCookies_OrderDeliveryDate/js/form/element/select',
                    'config' => [
                        'customScope' => 'shippingAddress',
                        'template' => 'ui/form/field',
                        'elementTmpl' => 'MilkJarCookies_OrderDeliveryDate/form/element/select',
                        'id' => 'delivery-time-slot'
                    ],
                    'caption' => 'Please select delivery time slot',
                    'dataScope' => 'shippingAddress.delivery_time_slot',
                    'label' => 'Delivery Time Slot',
                    'provider' => 'checkoutProvider',
                    'visible' => true,
                    'validation' => [],
                    'options' => $this->_helper->getTimeSlot(),
                    'sortOrder' => 201,
                    'id' => 'delivery-time-slot',
                ];
            }else{
                $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
                ['shippingAddress']['children'][$container]['children']['delivery_time_slot'] = [
                    'component' => 'MilkJarCookies_OrderDeliveryDate/js/form/element/select',
                    'config' => [
                        'customScope' => 'shippingAddress',
                        'template' => 'ui/form/field',
                        'elementTmpl' => 'MilkJarCookies_OrderDeliveryDate/form/element/select',
                        'id' => 'delivery-time-slot'
                    ],
                    'caption' => 'Please select delivery time slot',
                    'dataScope' => 'shippingAddress.delivery_time_slot',
                    'label' => 'Delivery Time Slot',
                    'provider' => 'checkoutProvider',
                    'visible' => true,
                    'validation' => [],
                    'options' => $this->_helper->getTimeSlot(),
                    'sortOrder' => 201,
                    'id' => 'delivery-time-slot',
                ];
            }
        }
        // before place order
        if($this->_helper->getDisplayAt() == self::DELIVERY_FORM_DISPLAY_AT_REVIEW_PAYMENTS){
            $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
            ['payment']['children']['payments-list']['children']['before-place-order']['children']['shipping_arrival_comments'] = [
                'component' => 'Magento_Ui/js/form/element/textarea',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'ui/form/element/textarea',
                    'id' => 'shipping-arrival-comments',
                    'rows' => 5
                ],
                'dataScope' => 'shippingAddress.shipping_arrival_comments',
                'label' => 'Special Instructions',
                'provider' => 'checkoutProvider',
                'visible' => true,
                'validation' => [],
                'sortOrder' => 202,
                'id' => 'shipping-arrival-comments'
            ];
        }else{
            $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
            ['shippingAddress']['children'][$container]['children']['shipping_arrival_comments'] = [
                'component' => 'Magento_Ui/js/form/element/textarea',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'ui/form/element/textarea',
                    'id' => 'shipping-arrival-comments',
                    'rows' => 5
                ],
                'dataScope' => 'shippingAddress.shipping_arrival_comments',
                'label' => 'Special Instructions',
                'provider' => 'checkoutProvider',
                'visible' => true,
                'validation' => [],
                'sortOrder' => 202,
                'id' => 'shipping-arrival-comments'
            ];
        }
        return $jsLayout;
    }
}

In short: I am not quite sure how I can utilize the LayoutProcessorPlugin to overwrite the processPaymentConfiguration method or how to correctly overwrite that method so that I can overwrite the billing-address.js component.

1 Answer 1

0

You could overwrite the JS file in Your\Module\view\frontend\requirejs-config.js:

var config = {
    map: {
        "*": {
            "Magento_Checkout/js/view/billing-address": "MilkJarCookies_OrderDeliveryDate/js/view/billing-address"
        }
    }
};

Another way would be to manually replace the text in the config array at the end of your afterProcess plugin:

    $json = json_encode($jsLayout);
    $json = str_replace(
        'Magento_Checkout\/js\/view\/billing-address',
        'MilkJarCookies_OrderDeliveryDate\/js\/view\/billing-address',
        $json
    );
    $jsLayout = json_decode($json);

This could be made a lot more efficient, it's just an example.

1
  • The require.js way is the way I used to overwrite the billing-address.js file Commented Nov 21, 2016 at 18:13

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.