I am working through the Add a new field in the address form tutorial. I've copied the tutorial, and the custom field is appearing on my Checkout page. However the fields are not stored when submitting the checkout. In fact, when dumping the database, I can see that unique strings stored in the Custom Attribute field are not present in the dump. This is on a vanilla Magento 2.4.4 running locally in a Docker container on my Ubuntu desktop.
These are my files, what have I done wrong?
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="Dc_Foo" setup_version="0.0.1">
<sequence>
<module name="Magento_Customer" />
<module name="Magento_Checkout" />
</sequence>
</module>
</config>
registration.php
<?php
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Dc_Foo', __DIR__);
Plugin/Block/Checkout/LayoutProcessor.php
<?php
namespace Dc\Foo\Plugin\Block\Checkout;
use Magento\Checkout\Block\Checkout\LayoutProcessor as LayoutProcessor_stock;
class LayoutProcessor {
public function afterProcess(LayoutProcessor_stock $subject, array $jsLayout)
{
$customAttributeCode = 'foo';
$customField = [
'component' => 'Magento_Ui/js/form/element/abstract',
'config' => [
'customScope' => 'shippingAddress.custom_attributes',
'customEntry' => null,
'template' => 'ui/form/field',
'elementTmpl' => 'ui/form/element/input',
'tooltip' => [
'description' => 'The fine Foo field.',
],
],
'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
'label' => 'Foo',
'provider' => 'checkoutProvider',
'sortOrder' => 0,
'validation' => [
'required-entry' => false
],
'options' => [],
'filterBy' => null,
'customEntry' => null,
'visible' => true,
'value' => '' // value field is used to set a default value of the attribute
];
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField;
return $jsLayout;
}
}
etc/frontend/di.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="dc-foo-add-foo-to-addresses" type="Dc\Foo\Plugin\Block\Checkout\LayoutProcessor" sortOrder="10" />
</type>
</config>
view/frontend/web/js/action/set-shipping-information-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'] = {};
}
var attribute = shippingAddress.customAttributes.find(
function (element) {
return element.attribute_code === 'foo';
}
);
shippingAddress['extension_attributes']['foo'] = attribute.value;
// pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
return originalAction();
});
};
});
view/frontend/requirejs-config.js
var config = {
config: {
mixins: {
'Magento_Checkout/js/action/set-shipping-information': {
'Dc_Foo/js/action/set-shipping-information-mixin': true
},
}
}
};
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="foo" type="string" />
</extension_attributes>
</config>
I've then run the following CLI commands (output truncated with ... where appropriate):
$ bin/magento cache:clean
Cleaned cache types:
config
layout
block_html
collections
reflection
db_ddl
compiled_config
eav
customer_notification
config_integration
config_integration_api
full_page
config_webservice
translate
$ bin/magento module:enable Dc_Foo"
The following modules have been enabled:
- Dc_Foo
To make sure that the enabled modules are properly registered, run 'setup:upgrade'.
Cache cleared successfully.
Generated classes cleared successfully. Please run the 'setup:di:compile' command to generate classes.
Info: Some modules might require static view files to be cleared. To do this, run 'module:enable' with the --clear-static-content option to clear them.
$ bin/magento setup:upgrade
Cache types config flushed successfully
Cache cleared successfully
File system cleanup:
...
The directory '/var/www/foo/generated/metadata/' doesn't exist - skipping cleanup
...
Updating modules:
Cache cleared successfully
Schema creation/updates:
Module 'Dc_Foo':
...
Module 'Magento_ComposerRootUpdatePlugin':
Running data recurring...Web Setup Wizard installation of "magento/composer-root-update-plugin" failed; unable to load /var/www/html/composer.json.
...
Module 'Dc_Foo':
...
Enabling caches:
Current status:
layout: 1
block_html: 1
full_page: 1
Nothing to import.
Media files stored outside of 'Media Gallery Allowed' folders will not be available to the media gallery.
Please refer to Developer Guide for more details.
$ bin/magento setup:di:compile
Compilation was started.
Plugin list generation... 9/9 [============================] 100% 47 secs 430.0 MiB
Generated code and dependency injection configuration successfully.
Now, I see the field where I expect it on the Shipping Page:
And I see that the data was passed to the Review Page:
And I certainly completed the order:
But nothing in the fine database?!?
$ mysqldump -uroot -p foodb --skip-extended-insert --default-character-set=utf8mb4 -r dump-foo.sql
$ grep "happy-foo-field" dump-foo.sql
$ wc -l dump-foo.sql
25136 dump-foo.sql
$ head dump-foo.sql # The file is valid
-- MySQL dump 10.13 Distrib 8.0.31, for Linux (x86_64)
-- Host: localhost Database: foodb
-- Server version 8.0.28
/!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT /;
/!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS /;
/!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION /;
/!50503 SET NAMES utf8mb4 /;



quote_addresstable. When checking out as a logged-in Customer the field is in fact stored in thequote_addressdatabase table, so I see that the data is stored! However, the field is not shown in the Customer's dashboard. And though the field does display in the adminhtmlCustomersarea, the field is blank (the stored value is not presented there). In any case, whether you can help me with that or not, I am of course presenting the bounty to this wonderful answer. Thank you Tu Van! – dotancohen Feb 02 '23 at 12:49custom attribute, not anextension attribute, that means they are different, so you can't see the value of that extension attribute in admin customer area, customer dashboard. – Tu Van Feb 02 '23 at 17:13