Custom Shipping Address Field
Adding custom field to checkout shipping address frontend¶
1) Create the basic skeleton of module. Make sure to create dependency in Vendor/Module/etc/module.xml
to avoid bad things from happening.
<?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="EdmondsCommerce_Sms" setup_version="1.0.0">
<sequence>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
2) Create the Vendor/Module/Setup/InstallSchema.php
with contents below
<?php
namespace EdmondsCommerce\Sms\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class InstallSchema implements InstallSchemaInterface
{
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$connection = $installer->getConnection();
$connection
->addColumn(
$installer->getTable('quote_address'),
'sms',
[
'type' => \Magento\Framework\DB\Ddl\Table ::TYPE_TEXT,
'nullable' => true,
'default' => NULL,
'length' => 255,
'comment' => 'SMS Number',
'after' => 'fax'
]
);
$connection
->addColumn(
$installer->getTable('sales_order_address'),
'sms',
[
'type' => \Magento\Framework\DB\Ddl\Table ::TYPE_TEXT,
'nullable' => true,
'default' => NULL,
'length' => 255,
'comment' => 'SMS Number',
'after' => 'fax'
]
);
$installer->endSetup();
}
}
3) Create UpgradeData.php script with the content like
<?php
namespace EdmondsCommerce\Sms\Setup;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetup;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class UpgradeData implements UpgradeDataInterface
{
private $customerSetupFactory;
public function __construct(\Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory)
{
$this->customerSetupFactory = $customerSetupFactory;
}
public function upgrade(ModuleDataSetupInterface $setup,
ModuleContextInterface $context){
$setup->startSetup();
/** @var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerSetup->addAttribute('customer_address', 'sms', [
'label' => 'Mobile (Courier text notifications)',
'input' => 'text',
'type' => \Magento\Framework\DB\Ddl\Table ::TYPE_TEXT,
'source' => '',
'required' => false,
'position' => 333,
'visible' => true,
'system' => false,
'is_used_in_grid' => false,
'is_visible_in_grid' => false,
'is_filterable_in_grid' => false,
'is_searchable_in_grid' => false,
'backend' => ''
]);
$attribute = $customerSetup->getEavConfig()->getAttribute('customer_address', 'sms')
->addData(['used_in_forms' => [
'adminhtml_customer_address',
'adminhtml_customer',
'customer_address_edit',
'customer_register_address',
'customer_address',
]]);
$attribute->save();
$setup->endSetup();
}
}
3) Create a plugin in Vendor/Module/Plugin/{YourPluginName.php}
with content below which will register your extension attributes to be seen by checkout javascript.
<?php
namespace EdmondsCommerce\Sms\Plugin;
use Magento\Checkout\Block\Checkout\LayoutProcessor;
class SmsPlugin
{
public function afterProcess(LayoutProcessor $subject, $jsLayout) {
$customAttributeCode = 'sms';
$customField = [
'component' => 'Magento_Ui/js/form/element/abstract',
'config' => [
// 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',
'tooltip' => [
'description' => 'Mobile (Courier text notifications)',
],
],
'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
'label' => 'Custom SMS Attribute',
'provider' => 'checkoutProvider',
'sortOrder' => 0,
'validation' => [
'required-entry' => true
],
'options' => [],
'filterBy' => null,
'customEntry' => null,
'visible' => true,
];
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField;
return $jsLayout;
}
}
Vendor/Module/Plugin/{ShippngInformationManagementPlugin.php}
which will set your custom field with value from extension attributes.
<?php
namespace EdmondsCommerce\Sms\Plugin;
class ShippingInformationManagementPlugin
{
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) {
$sms = $shippingAddressExtensionAttributes->getSms();
$shippingAddress->setSms($sms);
}
}
}
4) Register those plugins in Vendor/Module/etc/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="sms_plugin" type="EdmondsCommerce\Sms\Plugin\SmsPlugin" sortOrder="1" />
</type>
<type name="Magento\Checkout\Model\ShippingInformationManagement">
<plugin name="sms_address_save_plugin" type="EdmondsCommerce\Sms\Plugin\ShippingInformationManagementPlugin" sortOrder="10"/>
</type>
</config>
5) Create javascript field which will extend the javascript part of shipping address
the file needs to be created under Vendor/Module/view/frontend/web/js/action/{set-shipping-infomation-mixin.js}
. (Could be any file name, just follow standards, and I think this should be the appropriate file name)
The contents of that file
/*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']['sms'] = shippingAddress.customAttributes['sms'];
// pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
return originalAction();
});
};
});
6) Include that file through requirejs inside Vendor/Module/view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Checkout/js/action/set-shipping-information': {
'EdmondsCommerce_Sms/js/action/set-shipping-information-mixin': true
}
}
}
};
6) And one more necessary step is creating Vendor/Module/etc/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="sms" type="string" />
</extension_attributes>
</config>
7) Register an observer, which will pass SMS field value from quote_address to order_address
by creating this file Vendor/Module/etc/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="sales_model_service_quote_submit_before">
<observer name="sms" instance="EdmondsCommerce\Sms\Observer\SalesModelServiceQuoteSubmitBefore" shared="false" />
</event>
</config>
7) Execute command below
php bin/magento module:enable EdmondsCommerce_Sms -c
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static:deploy
8) Check if your new field is inside checkout shipping address. Enjoy.