magento2: "select" custom customer address attribute does not render for new customer address

Custom customer address EAV attributes of 'type' => 'int' and 'input' => 'select' do not render after a logged-in customer creates a new address at checkout.

Preconditions (*)

  1. Base install of Magento 2.4.3-p1

Steps to reproduce (*)

  1. Create a custom module with a new setup patch data script to create a custom customer address attribute, with 'type' => 'int' and 'input' => 'select'. Ensure 'system' => false so it’s created as a “custom” attribute.

app/code/MarkShust/MyModule/registration.php

<?php declare(strict_types=1);

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,
    'MarkShust_MyModule',
    __DIR__
);

app/code/MarkShust/MyModule/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="MarkShust_MyModule">
        <sequence>
            <module name="Magento_Customer"/>
        </sequence>
    </module>
</config>

app/code/MarkShust/MyModule/Setup/Patch/Data/AddAddressClassificationAttribute.php

<?php declare(strict_types=1);

namespace MarkShust\MyModule\Setup\Patch\Data;

use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Eav\Model\Config as EavConfig;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Customer\Model\ResourceModel\Attribute as AttributeResourceModel;
use MarkShust\MyModule\Model\Config\Source\AddressClassification;
use Zend_Validate_Exception;

class AddAddressClassificationAttribute implements DataPatchInterface
{
    const ATTRIBUTE_CODE = 'address_classification';

    private AttributeResourceModel $attributeResourceModel;
    private EavConfig $eavConfig;
    private EavSetupFactory $eavSetupFactory;
    private ModuleDataSetupInterface $moduleDataSetup;

    public function __construct(
        AttributeResourceModel $attributeResourceModel,
        EavConfig $eavConfig,
        EavSetupFactory $eavSetupFactory,
        ModuleDataSetupInterface $moduleDataSetup
    ) {
        $this->attributeResourceModel = $attributeResourceModel;
        $this->eavConfig = $eavConfig;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->moduleDataSetup = $moduleDataSetup;
    }

    /**
     * @return array
     */
    public static function getDependencies(): array
    {
        return [];
    }

    /**
     * @return array
     */
    public function getAliases(): array
    {
        return [];
    }

    /**
     * @return $this
     * @throws LocalizedException
     * @throws AlreadyExistsException
     * @throws Zend_Validate_Exception
     */
    public function apply(): self
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $eavSetup->addAttribute(
            AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
            self::ATTRIBUTE_CODE,
            [
                'type' => 'int',
                'label' => 'Address Classification',
                'input' => 'select',
                'source' => AddressClassification::class,
                'required' => true,
                'default' => 0,
                'system' => false,
                'position' => 150,
                'sort_order' => 150,
            ]
        );
        $attribute = $this->eavConfig->getAttribute(
            AddressMetadataInterface::ENTITY_TYPE_ADDRESS,
            self::ATTRIBUTE_CODE
        );
        $attribute->setData('used_in_forms', [
            'adminhtml_customer_address',
            'customer_address_edit',
            'customer_register_address',
        ]);
        $this->attributeResourceModel->save($attribute);

        return $this;
    }
}

app/code/MarkShust/MyModule/Model/Config/Source/AddressClassification.php

<?php declare(strict_types=1);

namespace MarkShust\MyModule\Model\Config\Source;

use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use Magento\Eav\Model\Entity\Attribute\Source\SourceInterface;
use Magento\Framework\Data\OptionSourceInterface;

class AddressClassification extends AbstractSource implements OptionSourceInterface, SourceInterface
{
    public function getAllOptions(): array
    {
        return [
            [
                'value' => 0,
                'label' => 'Residential',
            ],
            [
                'value' => 1,
                'label' => 'Commercial',
            ],
        ];
    }
}
  1. Enable the module with bin/magento module:enable MarkShust_MyModule.
  2. Execute the setup patch data script by running bin/magento setup:upgrade.
  3. Go to frontend of the site and log in as a registered customer.
  4. Add a product to the cart and start checkout.
  5. At the Shipping step under Shipping Address, click New Address.
  6. Enter the new address info along with a value for the custom attribute, then click Ship Here.

Expected result (*)

  1. I expect to see the custom customer address attribute rendered just as the saved addresses do:

Screen Shot 2022-01-08 at 10 33 39 AM

  1. Note how saved addresses are created under a custom_attributes property. This differs from the data stored for the new customer address as explained in the Actual result info below. They are also stored as an object containing a label and value, as opposed to just an integer:

Screen Shot 2022-01-09 at 10 18 09 AM

  1. I’d expect the way the data assigned to the new customer address to be congruent with how data is stored for saved addresses.

Actual result (*)

  1. The new address is created, but the custom customer attribute does not display. Note how the attribute is stored as a child property directly on the newCustomerShippingAddress property, and as an integer (address_classification: 0).

Screen Shot 2022-01-08 at 10 33 10 AM


  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 1
  • Comments: 24 (8 by maintainers)

Most upvoted comments

Hi @engcom-Hotel, I tried reproducing the issue with the fresh Magento 2.4-develop instance and the issue is still reproducible. I created the custom module and added the patch script following the documentation and as per the reproducible steps mentioned by @markshust I was able to reproduce the issue. 34950

Based on this confirming the issue!

Thanks.