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,
];
}
}
Best Answer
I have solved the mentioned issue by changing code in set-billing-address-mixin.js