Php – Magento 2 custom address attribute not loading in address book in checkout page

magentomagento2magento2.2PHP

I created a Magento Module to 2.2.4 and 2.2.3 version that add a custom attribute in Shipping Address and Customer Address. The attribute works fine when new address is created in checkout page show my custom attribute and save in order address and quote address.

The problem is when load the address from the address book so my custom attribute not loading and it is required in shipping address and I canĀ“t go to payments

When edit the custom attribute in Customers > Address from Magento Admin is not saved. I set values into database manually to my custom attribute in customer address but not is loading in checkout page

So the custom attribute only works when writte a new address but not is saving in address book only in order and address quote so I set values manually in database but not works and I neeed that is load in my saved address when entry to checkout page.

Checkout page example

enter image description here

Please help me guys.

DD\Checkoutaddress\di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
        <plugin name="add_custom_field_checkout_form" type="DD\Checkoutaddress\Model\Plugin\Checkout\LayoutProcessor" sortOrder="100"/>
    </type>

    <type name="Magento\Checkout\Model\ShippingInformationManagement">
        <plugin name="save_custom_field" type="DD\Checkoutaddress\Model\Plugin\Checkout\SaveAddressInformation" />
    </type>
</config>

DD\Checkoutaddress\extension_attributes.xml

<?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="mobilenumber" type="string" />
    </extension_attributes>

    <extension_attributes for="Magento\Checkout\Api\Data\ShippingInformationInterface">
        <attribute code="mobilenumber" type="string" />
    </extension_attributes>
</config>

DD\Checkoutaddress\Model\Plugin\Checkout\LayoutProcessor.php

<?php
namespace DD\Checkoutaddress\Model\Plugin\Checkout;

class LayoutProcessor
{
    /**
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        array  $jsLayout
    ) {
        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
        ['shippingAddress']['children']['shipping-address-fieldset']['children']['mobilenumber'] = [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                'customScope' => 'shippingAddress.custom_attributes',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/input',
                'options' => [],
                'id' => 'custom-field'
            ],
            'dataScope' => 'shippingAddress.custom_attributes.mobilenumber',
            'label' => 'Mobile Number',
            'required' => true,
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => ['required-entry' => true],
            'sortOrder' => 69,
            'id' => 'mobilenumber'
        ]; 

        return $jsLayout;
    }
}

DD\Checkoutaddress\Model\Plugin\Checkout\SaveAddressInformation.php

<?php 
namespace DD\Checkoutaddress\Model\Plugin\Checkout;

class SaveAddressInformation
{
    protected $quoteRepository;

    public function __construct(
        \Magento\Quote\Model\QuoteRepository $quoteRepository
    ) {
        $this->quoteRepository = $quoteRepository;
    }


   /**
     * @param \Magento\Checkout\Model\ShippingInformationManagement $subject
     * @param $cartId
     * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
     */
    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
    ) {

        $shippingAddress = $addressInformation->getShippingAddress();
        $shippingAddressExtensionAttributes = $shippingAddress->getExtensionAttributes();

        if ($shippingAddressExtensionAttributes) {
            $mobilenumber = $shippingAddressExtensionAttributes->getmobilenumber();

            $shippingAddress->setMobilenumber($mobilenumber);
        }
    }
}

DD\Checkoutaddress\Setup\CustomerSetup.php

<?php

namespace DD\Checkoutaddress\Setup;

use Magento\Eav\Model\Config;
use Magento\Eav\Model\Entity\Setup\Context;
use Magento\Eav\Setup\EavSetup;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory;

class CustomerSetup extends EavSetup {

    protected $eavConfig;

    public function __construct(
        ModuleDataSetupInterface $setup,
        Context $context,
        CacheInterface $cache,
        CollectionFactory $attrGroupCollectionFactory,
        Config $eavConfig
        ) {
        $this -> eavConfig = $eavConfig;
        parent :: __construct($setup, $context, $cache, $attrGroupCollectionFactory);
    } 

    public function installAttributes($customerSetup) {
        $this -> installCustomerAttributes($customerSetup);
        $this -> installCustomerAddressAttributes($customerSetup);
    } 

    public function installCustomerAttributes($customerSetup) {

    } 

    public function installCustomerAddressAttributes($customerSetup) {


        $customerSetup -> addAttribute('customer_address',
            'mobilenumber',
            [
            'label' => 'Mobile Phone',
            'system' => 0,
            'user_defined' => true,
            'position' => 101,
            'sort_order' =>101,
            'visible' =>  true,
            'default_value' => '',
            'note' => '',
                        'type' => 'varchar',
                        'input' => 'text',
            ]
            );

        $customerSetup -> getEavConfig() -> getAttribute('customer_address', 'mobilenumber')->setData('is_user_defined',1)->setData('default_value','')-> setData('used_in_forms', ['adminhtml_customer_address', 'customer_register_address', 'customer_address_edit']) -> save();
    } 

    public function getEavConfig() {
        return $this -> eavConfig;
    } 
} 

DD\Checkoutaddress\Setup\InstallData.php

<?php

namespace DD\Checkoutaddress\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallData implements InstallDataInterface
{
    /**
     * EAV setup factory
     *
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * Init
     *
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        /** @var EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        if (version_compare($context->getVersion(), '1.0.0') < 0){

                $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                $customerSetup = $objectManager->create('DD\Checkoutaddress\Setup\CustomerSetup');
                $customerSetup->installAttributes($customerSetup);


                $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                $salesSetup = $objectManager->create('Magento\Sales\Setup\SalesSetup');
                $salesSetup->addAttribute('order_address', 'mobilenumber', ['type' =>'varchar']);

                $quoteSetup = $objectManager->create('Magento\Quote\Setup\QuoteSetup');                
                $quoteSetup->addAttribute('quote_address', 'mobilenumber', ['type' =>'varchar']);
        }

    }
}

require-config.js

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                'DD_Checkoutaddress/js/action/set-shipping-infomation-mixin': true
            }
        }
    }
};

set-shipping-infomation-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'] = {};
            }

            shippingAddress['extension_attributes']['mobilenumber'] = shippingAddress.customAttributes['mobilenumber'];
            // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
            return originalAction();
        });
    };
});

Best Answer

Customer table in the database is different for save the book address for shipping and billing address, for this, you have need to be added following in Installation.php

$eavSetup->addAttribute('customer_address', 'phonecode', 
[
'type' => 'varchar',
'input' => 'text',
'label' => 'phonecode',
'visible' => true,
'required' => false,
'user_defined' => true,
'system'=> false,
'group'=> 'General',
'global' => true,
'visible_on_front' => true,
]);
$customAttribute = $this->eavConfig->getAttribute('customer_address', 
'phonecode');
$customAttribute->setData(
'used_in_forms',
['adminhtml_customer_address','customer_address_edit','customer_register_address'] //list of forms where you want to display the custom attribute
);

It will add a different attribute in 'eav_attribute' table to save address different, then you can submit the form with a custom field, data will be saved in 'customer_address_entity_varchar'.

Related Topic