1

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>
0

you need to implement sales_quote_address_save_after for that

more info you can find https://web4pro.net/blog-news/magento-2-add-custom-attribute-customers-address/

0

I had the same issue and I was struggling with this for days.

Try adding the etc/fieldset.xml:

         <field name="address_email">
             <aspect name="to_customer_address" />
             <aspect name="to_order_address" />
         </field>
     </fieldset>

And a plugin for Customer Address:

        <plugin disabled="false" name="module_quote_model_address" sortOrder="10" 
        type="Vendor\Module\Plugin\Customer\Model\Address"/>
    </type>

and use the beforeUpdateData function to save your custom attribute.

Hope it helps!

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.