I'm trying to define a new customer address attribute that will be available in all the customer address forms (backend, frontend, checkout). I've used the information provided here:
https://devdocs.magento.com/guides/v2.2/howdoi/checkout/checkout_new_field.html
I've also read and tried to apply a lot of posts and articles I found in sources like Stack Exchange and in other websites found via Google. So far I've managed to get the attribute in all forms, but the value is only saved to the database in the admin address form; in the frontend address forms (customer section and checkout section) the attribute value is simply ignored. All the posts, articles and answers I've checked haven't helped. Could anyone please tell me if I'm missing something?
Here are all the relevant code snippets:
1.- Install script:
class InstallData implements InstallDataInterface
{
public function install(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
) {
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerSetup->addAttribute('customer_address', 'address_email', array(
'type' => 'varchar',
'input' => 'text',
'label' => 'Address E-mail',
'global' => 1,
'visible' => 1,
'required' => 0,
'user_defined' => 1,
'system'=> 0,
'group'=> 'General',
'visible_on_front' => 1,
));
$customerSetup->getEavConfig()->getAttribute('customer_address', 'address_email')
->setUsedInForms(array('adminhtml_customer_address', 'customer_address_edit', 'customer_register_address', 'customer_address'))
->save();
}
}
2.- di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Rokanthemes\OpCheckout\Block\Checkout\LayoutProcessor">
<plugin name="changeAddressFields" type="Vendor\AddressCustomization\Plugin\Block\Checkout\LayoutProcessor" sortOrder="100" disabled="false"/>
</type>
<type name="Magento\Framework\Api\DataObjectHelper">
<plugin name="move-extension-attributes" type="Vendor\AddressCustomization\Plugin\Api\DataObjectHelper" sortOrder="20"/>
</type>
<type name="Magento\Sales\Block\Adminhtml\Order\View\Info">
<plugin name="render-address-email" type="Vendor\AddressCustomization\Plugin\Block\Adminhtml\Order\View\Info" sortOrder="20"/>
</type>
3.- Plugins
namespace Vendor\AddressCustomization\Plugin\Api;
class DataObjectHelper
{
public function beforePopulateWithArray($helper, $dataObject, array $data, $interfaceName)
{
switch ($interfaceName) {
case 'Magento\Sales\Api\Data\OrderAddressInterface':
if (isset($data['extension_attributes']) && ($data['extension_attributes'] instanceof \Magento\Quote\Api\Data\AddressExtensionInterface)) {
$data['extension_attributes'] = $data['extension_attributes']->__toArray();
}
break;
case 'Magento\Customer\Api\Data\AddressInterface':
if (isset($data['extension_attributes']) && ($data['extension_attributes'] instanceof \Magento\Quote\Api\Data\AddressExtensionInterface)) {
$data['extension_attributes'] = $data['extension_attributes']->__toArray();
if (isset($data['extension_attributes']['address_email'])){
$data['address_email'] = $data['extension_attributes']['address_email'];
}
if (isset($data['extension_attributes']['is_company'])){
$data['is_company'] = $data['extension_attributes']['is_company'];
}
}
break;
case 'Magento\Quote\Api\Data\TotalsInterface':
unset($data['extension_attributes']);
break;
}
return array($dataObject, $data, $interfaceName);
}
}
-
namespace Vendor\AddressCustomization\Plugin\Block\Adminhtml\Order\View;
class Info
{
public function beforeGetFormattedAddress($block, $address)
{
if ($attributes = $address->getExtensionAttributes()) {
$address->setAddressEmail($attributes->getAddressEmail());
}
return array($address);
}
}
-
namespace Vendor\AddressCustomization\Plugin\Block\Checkout;
class LayoutProcessor
{
....
public function afterProcess(
\Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
array $jsLayout
)
{
....
$customAttributes = array(
'address_email' => array(
'component' => 'Magento_Ui/js/form/element/abstract',
'config' => [
'additionalClasses' => 'one-field',
'placeholder' => 'Shipping destination e-mail',
// customScope is used to group elements within a single form (e.g. they can be validated separately)
'customScope' => 'shippingAddress.custom_attributes',
'customEntry' => null,
'template' => 'ui/form/field',
'elementTmpl' => 'ui/form/element/input',
],
'dataScope' => 'shippingAddress.custom_attributes.address_email',
'label' => __('Destination E-mail'),
'provider' => 'checkoutProvider',
'sortOrder' => 1000,
'validation' => [
'required-entry' => false
],
'options' => [],
'filterBy' => null,
'customEntry' => null,
'visible' => false,
),
);
foreach ($customAttributes as $customAttributeCode => $customField) {
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField;
}
}
}
4.- Javascript mixins
file app/code/Vendor/AddressCustomization/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Checkout/js/action/set-shipping-information': {
'Vendor_AddressCustomization/js/action/set-shipping-information-mixin': true
},
}
}
};
-
file app/code/Vendor/AddressCustomization/view/frontend/web/js/action/set-shipping-information-mixin.js
/*jshint browser:true jquery:true*/
/*global alert*/
define([
'jquery',
'mage/utils/wrapper',
'Magento_Checkout/js/model/quote'
], function ($, wrapper, quote) {
'use strict';
return function (setShippingInformationAction) {
return wrapper.wrap(setShippingInformationAction, function (originalAction) {
var shippingAddress = quote.shippingAddress();
if (shippingAddress['extension_attributes'] === undefined) {
shippingAddress['extension_attributes'] = {};
}
if (shippingAddress.customAttributes === undefined) {
shippingAddress.customAttributes = {};
}
if (shippingAddress.customAttributes['address_email'] instanceof Object) {
shippingAddress.customAttributes['address_email'] = shippingAddress.customAttributes['address_email'].value;
}
shippingAddress['extension_attributes']['address_email'] = shippingAddress.customAttributes['address_email'];
// pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
return originalAction();
});
};
});
5.- Extension attributes
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\AddressInterface">
<attribute code="address_email" type="string" />
</extension_attributes>
<extension_attributes for="Magento\Sales\Api\Data\OrderAddressInterface">
<attribute code="address_email" type="string"/>
</extension_attributes>
<extension_attributes for="Magento\Customer\Api\Data\AddressInterface">
<attribute code="address_email" type="string"/>
</extension_attributes>
</config>