How To

Magento 2: How to Add Custom Field at Customer Address Form and Save its Value

Hello Magento Friends,

In today’s Magento 2 tutorial, I am going to explain How to Add a Custom Field in the Customer Address Form and Save its Value in the Magento 2.

Magento 2 offers a robust framework that allows developers to extend and enhance its functionalities. One common requirement is the need to add custom fields to the customer address form and store the values efficiently. In this blog post, we’ll explore the process of adding a custom field to the customer address form in Magento 2 and saving its value.

Steps to Add Custom Field at Customer Address Form and Save its Value in Magento 2:

Step 1: Create registration.php file inside the Extension folder.

app\code\Vendor\Extension\

Then add the code as follows

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_Extension',
    __DIR__
);

Step 2: Now, create module.xml file inside the etc folder.

app\code\Vendor\Extension\etc\

And include the below-mentioned code

<?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="Vendor_Extension" setup_version="1.0.0"/>
</config>

Step 3: Then create Customfield.php file inside Field folder.

app\code\Vendor\Extension\Block\Address\Field\

After that, add the following piece of code

<?php
namespace Vendor\Extension\Block\Address\Field;

use Magento\Framework\View\Element\Template;

class Customfield extends Template
{
    /**
     * @var string
     */    protected $_template = 'address/edit/field/customfield.phtml';

    /**
     * @var \Magento\Customer\Api\Data\AddressInterface
     */    protected $_address;

    /**
     * @return string
     */    public function getCustomfieldValue()
    {

        /** @var \Magento\Customer\Model\Data\Address $address */        $address = $this->getAddress();
        $customfieldValue = $address->getCustomAttribute('customfield');
        if (!$customfieldValue instanceof \Magento\Framework\Api\AttributeInterface) {
            return '';
        }

        return $customfieldValue->getValue();
    }

    /**
     * Return the associated address.
     *
     * @return \Magento\Customer\Api\Data\AddressInterface
     */    public function getAddress()
    {
        return $this->_address;
    }

    /**
     * Set the associated address.
     *
     * @param \Magento\Customer\Api\Data\AddressInterface $address
     */    public function setAddress($address)
    {
        $this->_address = $address;
    }
}

Step 4: Next, create di.xml file inside the frontend folder.

app\code\Vendor\Extension\etc\frontend\

And add the code as given below

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
      <type name="Magento\Customer\Block\Address\Edit">
        <plugin name="checkout-fields-block-address-form" type="Vendor\Extension\Plugin\AddExtraFieldToAddressForm" />
    </type> 
     <type name="Magento\Customer\Api\AddressRepositoryInterface">
        <plugin name="checkout-fields-repository-address" type="Vendor\Extension\Plugin\AddExtraFieldToAddressEntity" />
    </type> 
   
</config>

Step 5: After that, create extension_attributes.xml file inside etc folder.

app\code\Vendor\Extension\etc\

Now add the following code snippet

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Checkout\Api\Data\ShippingInformationInterface">
        <attribute code="customfield" type="string" />
    </extension_attributes>
      <extension_attributes for="Magento\Customer\Api\Data\AddressInterface">
        <attribute code="customfield" type="string" />
    </extension_attributes>
    <extension_attributes for="Magento\Quote\Api\Data\AddressExtensionInterface">
        <attribute code="customfield" type="string" />
    </extension_attributes>
</config>

Step 6: Then create AdditionalAttributes.php file inside Address folder.

app\code\Vendor\Extension\Model\Address\

Now include the following code

<?php
namespace Vendor\Extension\Model\Address;

use Magento\Framework\Api\AbstractSimpleObject;

class AdditionalAttributes extends AbstractSimpleObject implements \Magento\Customer\Api\Data\AddressExtensionInterface
{
    /**
     * @param string $note
     * @return void
     */    public function setCustomfield($customfield)
    {
        $this->setData('customfield', $customfield);
    }

    /**
     * @return mixed|null
     */    public function getCustomfield()
    {
        return $this->_get('customfield');
    }
}

Step 7: Then create AddExtraFieldToAddressEntity.php file inside Plugin folder.

app\code\Vendor\Extension\Plugin\

Now add the following code

<?php
namespace Vendor\Extension\Plugin;

use Magento\Customer\Api\AddressRepositoryInterface as Subject;
use Magento\Customer\Api\Data\AddressInterface as Entity;

/**
 * Class AddNoteFieldToAddressEntity
 *
 * @package Yireo\ExampleAddressFieldNote\Plugin
 */class AddExtraFieldToAddressEntity
{
    protected $httpRequest;
    protected $logger;

    public function __construct(
        \Magento\Framework\App\RequestInterface $httpRequest,
        \Magento\Framework\Logger\Monolog $logger
    )
    {
        $this->httpRequest = $httpRequest;
        $this->logger = $logger;
    }

    /**
     * @param Subject $subject
     * @param Entity $entity
     *
     * @return Entity
     */    public function afterGetById(Subject $subject, Entity $entity)
    {
        $extensionAttributes = $entity->getExtensionAttributes();
        if ($extensionAttributes === null) {
            return $entity;
        }

        $customfield = $this->getCustomfieldByEntityId($entity);
        $extensionAttributes->setCustomfield($customfield);
        $entity->setExtensionAttributes($extensionAttributes);

        return $entity;
    }

    /**
     * @param Subject $subject
     * @param Entity $entity
     *
     * @return [Entity]
     */    public function beforeSave(Subject $subject, Entity $entity)
    {
        $extensionAttributes = $entity->getExtensionAttributes();
        if ($extensionAttributes === null) {
            return [$entity];
        }

        // @todo: Really dirty hack, because Magento\Customer\Controller\Address\FormPost does not support Extension Attributes
        $customfield = $this->httpRequest->getParam('customfield');
        $entity->setCustomAttribute('customfield', $customfield);

        return [$entity];
    }

    /**
     * @param Entity $entity
     *
     * @return string
     */    private function getCustomfieldByEntityId(Entity $entity)
    {
        $attribute = $entity->getCustomAttribute('customfield');
        if ($attribute) {
            return $attribute->getValue();
        }

        return '';
    }
}

Step 8: Then create AddExtraFieldToAddressForm.php file inside Plugin folder.

app\code\Vendor\Extension\Plugin\

And add the code as follows

<?php
namespace Vendor\Extension\Plugin;

use Magento\Customer\Block\Address\Edit as Subject;
use Vendor\Extension\Block\Address\Field\Customfield as CustomfieldBlock;

class AddExtraFieldToAddressForm
{
    /**
     * @param Subject $subject
     * @param string $html
     *
     * @return string
     */    public function afterToHtml(Subject $subject, $html)
    {
        $customfieldBlock = $this->getChildBlock(CustomfieldBlock::class, $subject);
        $customfieldBlock->setAddress($subject->getAddress());
        $html = $this->appendBlockBeforeFieldsetEnd($html, $customfieldBlock->toHtml());

        return $html;
    }

    /**
     * @param string $html
     * @param string $childHtml
     *
     * @return string
     */    private function appendBlockBeforeFieldsetEnd($html, $childHtml)
    {
        $pregMatch = '/\<\/fieldset\>/';
        $pregReplace = $childHtml . '\0';
        $html = preg_replace($pregMatch, $pregReplace, $html, 1);

        return $html;
    }

    /**
     * @param $parentBlock
     *
     * @return mixed
     */    private function getChildBlock($blockClass, $parentBlock)
    {
        return $parentBlock->getLayout()->createBlock($blockClass, basename($blockClass));
    }
}

Step 9: Next create UpgradeData.php file inside Setup folder.

app\code\Vendor\Extension\Setup\

Then add the below given code

<?php

namespace Vendor\Extension\Setup;

use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;

class UpgradeData implements UpgradeDataInterface
{
   private $customerSetupFactory;

   public function __construct(\Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory)
   {
       $this->customerSetupFactory = $customerSetupFactory;
   }

   public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
   {
       $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
      
           $customerSetup->addAttribute('customer_address', 'customfield', [
               'label' => 'Custom Field',
               'input' => 'text',
               'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
               'source' => '',
               'required' => false,
               'position' => 90,
               'visible' => true,
               'system' => false,
               'is_used_in_grid' => true,
               'is_visible_in_grid' => true,
               'is_filterable_in_grid' => false,
               'is_searchable_in_grid' => false,
               'frontend_input' => 'hidden',
               'backend' => ''
           ]);

              $attribute=$customerSetup->getEavConfig()
                ->getAttribute('customer_address','customfield')                                  
                ->addData(['used_in_forms' => [
                   'adminhtml_customer_address',
                   'adminhtml_customer',
                   'customer_address_edit',
                   'customer_register_address',
                   'customer_address',
                   'checkout_register',
                   'adminhtml_checkout'
                  ]
                ]);
           $attribute->save();
   }
}

Step 10: At last, create customfield.phtml file inside field folder.

app\code\Vendor\Extension\view\frontend\templates\address\edit\field\

Finally, add the code as follows

<div class="field customfield">
    <label class="label" for="customfield"><span><?php /* @escapeNotVerified */ echo __('Custom Field') ?></span></label>
    <div class="control">
        <input type="text" name="customfield" value="<?php echo $block->getCustomfieldValue() ?>" title="<?php /* @escapeNotVerified */ echo __('Custom Field') ?>" id="customfield" class="input-text" >
    </div>
</div>

Output:

After following the above steps, you can see that the custom field has been added to the customer address.

Conclusion:

Customizing the customer address form in Magento 2 allows you to collect specific information tailored to your business needs. By following the steps outlined in this blog post, you can seamlessly integrate custom fields, enhancing the overall customer experience on your Magento e-commerce platform.

If you face any difficulty while implementing the above steps, let me know through the comment section. For more customization requirements, get in touch with experienced Magento Developers.

Happy Coding!

Click to rate this post!
[Total: 0 Average: 0]
Dhiren Vasoya

Dhiren Vasoya is a Director and Co-founder at MageComp, Passionate 🎖️ Certified Magento Developer👨‍💻. He has more than 9 years of experience in Magento Development and completed 850+ projects to solve the most important E-commerce challenges. He is fond❤️ of coding and if he is not busy developing then you can find him at the cricket ground, hitting boundaries.🏏

Recent Posts

Mastering Tailwind CSS in Laravel: A Comprehensive Guide

Tailwind CSS has emerged as a powerful utility-first CSS framework, offering developers a unique approach…

2 days ago

React Native or Flutter in 2024

The mobile app development field has witnessed a rapid revolution over the past few years.…

3 days ago

Magento 2: How To Call JS on the Checkout Page?

Hello Magento mates, Today we will learn to add a call JS on the checkout…

6 days ago

Boost Your SEM Game: Unveiling the Top 10 Tools for Marketers in 2024

Business survival in today’s digital world has become extremely difficult. Using traditional marketing techniques is…

1 week ago

Five Essential Payroll Compliance Tips for eCommerce Startups

Are you setting up a payroll system for your eCommerce startup? Ensuring compliance with myriad…

1 week ago

Optimizing Laravel Blade: Unlocking Advanced Fetcher Techniques

In the expansive universe of Laravel development, Blade serves as the stellar templating engine, propelling…

1 week ago