4

I am trying to add an extra custom field in checkout billing address. By refering magento2 documentationhere I am able to add a custom field in shipping address and value can be stored in DB by observing the event sales_model_service_quote_submit_before.

I am trying the same for billing address but it throws an extension_attributes is null error . Please find the code below.

For shipping address its all working fine . In the billing address custom field can be seen but throws error upon saving

Steps 1. Added fieldset.xml 2. Added extension_attributes.xml 3. Added plugin for LayoutProcessor 4. Added requirejs-config.js 5. Added set-billing-address-mixin.js 6. Added installData

Pls refer LayoutProcessor.php , InstallData and set-billing-address-mixin.js

installData

added customer_address attribute and used in forms adminhtml_customer_address', 'customer_address_edit', 'customer_register_address and added column in quote_address and sales_order_address.

set-billing-address-mixin.js

 define([
        'jquery',
        'mage/utils/wrapper',
        'Magento_Checkout/js/model/quote'
    ], function ($, wrapper,quote) {
        'use strict';

        return

 function (setBillingAddressAction) {

        return wrapper.wrap(setBillingAddressAction, function (originalAction) {
            var billingAddress = quote.billingAddress();
            if (billingAddress['extension_attributes'] === undefined) {
                billingAddress['extension_attributes'] = {};
            }

            /***
             * custom field
             */
            billingAddress['extension_attributes']['customfield'] = billingAddress.customAttributes['customfield'];


            return originalAction();
        });
    };
});

LayoutProcessor

<?php
namespace Example\CheckoutField\Plugin\Checkout\Model\Checkout;
use Example\CheckoutField\Helper\Data as ExampleHelperData;
use Magento\Framework\App\ObjectManager;
class LayoutProcessor
{
    protected $helper;

    public $customAttributePosition = 'customfield';

    public function __construct(
        ExampleHelperData $helper
    ){
        $this->helper = $helper;
    }

    /**
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject, array $jsLayout
    )
    {
        if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
            ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']
        )) {
            $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$this->customAttributePosition] = $this->getCustomfield('shippingAddress');

        }


        if(isset($jsLayout['components']['checkout']['children']['steps']['children']
            ['billing-step']['children']['payment']['children']
            ['payments-list'])) {

            $paymentForms = $jsLayout['components']['checkout']['children']['steps']['children']
            ['billing-step']['children']['payment']['children']
            ['payments-list']['children'];

            foreach ($paymentForms as $paymentGroup => $groupConfig) {
                if (isset($groupConfig['component']) AND $groupConfig['component'] === 'Magento_Checkout/js/view/billing-address') {

                    $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
                    ['payment']['children']['payments-list']['children'][$paymentGroup]['children']['form-fields']['children'][$this->customAttributePosition]= $this->getCustomfieldBilling($paymentGroup);


                }
            }
        }

        return $jsLayout;
    }

    public function getCustomfield($type){
        return [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                // customScope is used to group elements within a single form (e.g. they can be validated separately)
                'customScope' => $type.'.custom_attributes',
                'customEntry' => null,
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/input',
                'id' => 'customfield'
            ],
            'dataScope' => $type.'.custom_attributes' . '.' . $this->customAttributePosition,
            'label' => 'customfield',
            'provider' => 'checkoutProvider',
            'sortOrder' => 55,
            'id' => 'customfield',
            'validation' => [],
            'options' => [],
            'filterBy' => null,
            'customEntry' => null,
            'visible' => true,
        ];
    }
    public function getCustomfieldBilling($paymentMethodCode){
        $paymentMethodCode = str_replace('-form', '', $paymentMethodCode);
        return [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                // customScope is used to group elements within a single form (e.g. they can be validated separately)
                'customScope' => 'billingAddress' . $paymentMethodCode .'.custom_attributes',
                'customEntry' => null,
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/input',
                'id' => 'customfield'
            ],
            'dataScope' => 'billingAddress' . $paymentMethodCode .'.custom_attributes' . '.' . $this->customAttributePosition,
            'label' => 'customfield',
            'provider' => 'checkoutProvider',
            'sortOrder' => 55,
            'id' => 'customfield',
            'validation' => [],
            'options' => [],
            'filterBy' => null,
            'customEntry' => null,
            'visible' => true,
        ];
    }
}
1

I have solved the mentioned issue by changing code in set-billing-address-mixin.js

define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/action/get-payment-information'
], function ($, wrapper,quote) {
    'use strict';

    return function (setBillingAddressAction) {

        return wrapper.wrap(setBillingAddressAction, function (originalAction) {            
            var billingAddress = quote.billingAddress();
            var getPaymentInformationAction = getPaymentInformationAction;
            if (billingAddress && billingAddress.customAttributes) {
                billingAddress['extension_attributes'] = {};
                billingAddress['extension_attributes']['customfield'] = billingAddress.customAttributes['customfield'];

            }
            return originalAction();
        });
    };
});
| improve this answer | |
  • Hi Ajay, is it works for existing customer and billing address consider as a new address? – Amitkumar solanki Mar 11 '19 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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