0

I'm trying to add a custom attribute in Customer Address in Magento 2.3.1 with Wamp (PHP 7.2.25).

I created a custom attribute and additional columns in quote, sales_order_address and quote_address:

    private function createAttribute($code,$desc,$sortOrder)
    {
        $this->eavSetup->addAttribute(
           AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
            $code,
            [
                'label' => $desc,
                'type' => 'varchar',
                'input' => 'text',
                'visible' => true,
                'required' => false,
                'position' => $sortOrder,
                'sort_order' => $sortOrder,
                'system' => false
            ]
        );

        $attribute = $this->eavConfig->getAttribute(
            AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
            $code
        );

        $attribute->setData(
            'used_in_forms',
            [   'adminhtml_customer_address',
                'adminhtml_customer',
                'customer_address_edit',
                'customer_register_address',
                'customer_address']
        );

        $attribute->save();
    }

    private function addTableColumn($tableName,$fieldCode,$length,$fieldDesc)
    {
        $this->setup->getConnection()->addColumn(
        $this->setup->getTable($tableName),
            $fieldCode,
            [
                'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                'length' => $length,
                'nullable' => true,
                //'default' => '',
                'comment' => $fieldDesc
            ]
        );
    }

I created layout plugin with /etc/frontend/di.xml --> "Magento\Checkout\Block\Checkout\LayoutProcessor":

    private function buildJsLayout($customAttributeCode,$customAttributeId,$customAttributeDescription,$sortOrder,$scope,$length)
    {
        $this->logger->debug('Hrm_OrderCustomization - LayoutProcessorPlugin - buildJsLayout - ' . $customAttributeCode);

        $this->jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] =
        [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                'customScope' => $scope,
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/input',
                'additionalClasses' => ' col-mp mp-6',
                'options' => [],
                'id' => $customAttributeId
            ],
            'dataScope' => $scope . '.' . $customAttributeCode,
            'label' => $customAttributeDescription,
            'provider' => 'checkoutProvider',
            'sortOrder' => $sortOrder,
            'validation' => ['max_text_length' => $length,'min_text_length' => $length],
            'visible' => true,
            'value' =>  '',
            'id' => $customAttributeId
        ];
    }

extension_attribute:

    <?xml version="1.0"?>
    <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="custom_attribute" type="string" />
        </extension_attributes>
    </config>

I handled the js:

  • create-shipping-address --> create-shipping-address-mixin
  • set-shipping-information --> set-shipping-information-mixin
  • create-billing-address --> set-billing-address-mixin
  • place-order --> set-billing-address-mixin

and i added observe event, /etc/events.xml --> "sales_model_service_quote_submit_before", and AddressManagementPlugins, /etc/di.xml --> "Magento\Checkout\Model\ShippingInformationManagement", "Magento\Quote\Model\BillingAddressManagement", "Magento\Quote\Model\Quote\Address\BillingAddressPersister".

I also added the attribute in the admin (and customer account page) like this:

     <type name="Magento\Customer\Block\Address\Edit">
        <plugin name="customer-edit-plugin" type="Hrm\OrderCustomization\Plugin\Magento\Customer\AddressEditPlugin" sortOrder="10"/>
     </type>

    public function afterGetNameBlockHtml(
        \Magento\Customer\Block\Address\Edit $edit,
        $result
    ) {
        $block = $this->layout->createBlock(
            'Vendor\Module\Block\Customer\Address\Form\Edit\CustomTemplate',
            'vendor_order_customization'
        );
        return $result . $block->toHtml();
    }

CustomTemplate:

        protected function _toHtml()
    {
        $customWidgetBlock = $this->getLayout()->createBlock(
            'Vendor\Module\Block\Customer\Widget\CustomWidget'
        );

        $customWidgetBlock->setAddress($this->address);

        return $customWidgetBlock->toHtml();
    }

widget has all get methods (getId, vatLabelDesc ecc...) and getValue():

    protected function _construct() 
    {
        parent::_construct();
        $this->setTemplate('widget/customerAddress.phtml');
    }

    public function getValue()
        {
            $address = $this->getAddress();
            if($address instanceOf AddressInterface)
            {
                    $attr = $address->getCustomAttribute('custom_attribute')
                                ? $address->getCustomAttribute('custom_attribute')->getValue()
                                : null;

                    return $attr;
            }
            return null;
        }

and the phtml:

<div class="field custom_attribute<?php if ($block->isRequired()) echo 'required'; ?>">
    <label class="label" for="<?php echo $block->escapeHtml($block->getId()); ?>">
        <span><?php echo $block->escapeHtml($block->getLabel()); ?></span>
    </label>
    <div class="control">
        <input  type="text" 
                id="<?php echo $block->escapeHtml($block->getId()); ?>"
                name="<?php echo $block->escapeHtml($block->getName()); ?>"    
                value="<?php echo $block->escapeHtml($block->getValue()); ?>"
                title="<?php echo $block->escapeHtml($block->getLabel()); ?>"
                class="input-text"
            <?php /** @escapeNotVerified */ echo $block->getParams() ?>
            <?php if ($block->isRequired()) echo ' data-validate="{required:true}"' ?> />
    </div>
</div>

and finally i modified the HTML Address Templates in Admin Store --> configuration --> CustomerCustomization, adding:

{{depend custom_attribute}}Attribute: {{var custom_attribute}}{{/depend}}

well... with this code, the field is saved in table sales_order_address and I can see the value in order details, I can change the value from Admin-Customer or Customer-AddressBook and the new value is loaded correctly on the checkout page, but I have 2 problems:

  • if I add a new address in checkout page (or I edit an existing one from the checkout), the custom_attribute value is not saved in CustomerAddress but only in that specific order
  • if the customer has not any address, in checkout page the custom_attribute value doesn't exist in quote.shippingAddress.customAttribute (js mixin) and it cannot be saved even in the DB table

Instead trying to add the property 'user_defined' => true to the attribute I can save the value in sales_order_address from the checkout page, even if it's a new address BUT... in Admin CustomerAddress I can't save any value and I can't see the value in Order details anymore.

Sorry for the length of this Question and I hope I have explained myself well, Thanks

1 Answer 1

0

I solved second point (unlogged customer or customer without addresses) using 'user_defined' => false and overriding "Magento_Checkout/js/model/new-customer-address". Before RETURN i added:

        if (addressData['custom_attributes'] === undefined && addressData['custom_attribute'] != undefined) {
           addressData['custom_attributes'] = [];
           addressData['custom_attributes']['custom_attribute'] = {'attribute_code': 'custom_attribute',
                                                        'value': 
           addressData['custom_attribute']};
        }

but I still can't save the new field in customer address at place order.

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.