I will try to answer your question(s).
No. This is not a correct way to add custom attributes to the shipping address form. You do not need to edit new-customer-address.js
. Indeed, this JS file lists all predefined address attributes and matches corresponding backend interface \Magento\Quote\Api\Data\AddressInterface
but Magento provides ability to pass any custom attributes to backend without modification of the backend/frontend components.
Mentioned JS component has customAttributes
property. Your custom attributes will be automatically handled if their $dataScopePrefix
is 'shippindAddress.custom_attributes
'.
If I understood your question correctly, you have data that is not a part of customer address but you need to send it to backend as well. The answer to this question is:
It depends. For instance, you can choose the following approach: add custom form to checkout page that includes all your extra fields (like comment, invoice request etc)
, add JS logic that will handle this form based on some events, and provide a custom service that will receive the data from frontend and store it somewhere for future use.
All official documentation related to checkout is located at http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html. The term static refers to the forms where all the fields are already known/predefined (for instance: form will always have 2 text fields with predefined labels) and cannot change based on some settings in the backend.
Such forms can be declared using layout XML configuration
. On the other hand, term dynamic refers to forms whose field set can change (for instance: checkout form can have more/less fields based on configuration settings).
In this case the only way to declare such form is to use LayoutProcessor
plugin.
:) Magento tries to cover as much possible use cases that can be significant to the merchants during Magento use/customization as possible. Sometimes this leads to situation when some simple use cases become more complex.
Hope, this helps.
=========================================================================
OK... Lets write some code ;)
- PHP code that inserts additional field in LayoutProcessor
========
/**
* @author aakimov
*/
$customAttributeCode = 'custom_field';
$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' => 'Yes, this works. I tested it. Sacrificed my lunch break but verified this approach.',
],
],
'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
'label' => 'Custom 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;
As I already mentioned, this will add your field to customAttributes
property of the JS address object. This property was designed to contain custom EAV address attributes and is related to \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributes
method.
The code above will automatically handle local storage persistence on frontend. You can get your field value from local storage using checkoutData.getShippingAddressFromData()
(where checkoutData
is Magento_Checkout/js/checkout-data
).
- Add mixin to change the behavior of 'Magento_Checkout/js/action/set-shipping-information' (this component
is responsible for data submission between shipping and billing
checkout steps)
========
2.1. Create your_module_name/view/frontend/requirejs-config.js
/**
* @author aakimov
*/
var config = {
config: {
mixins: {
'Magento_Checkout/js/action/set-shipping-information': {
'<your_module_name>/js/action/set-shipping-information-mixin': true
}
}
}
};
2.2. Create your_module_name/view/frontend/web/js/action/set-shipping-information-mixin.js
/**
* @author aakimov
*/
/*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'] = {};
}
// you can extract value of extension attribute from any place (in this example I use customAttributes approach)
shippingAddress['extension_attributes']['custom_field'] = shippingAddress.customAttributes['custom_field'];
// pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
return originalAction();
});
};
});
- Create your_module_name/etc/extension_attributes.xml
========
<?xml version="1.0"?>
<!--
/**
* @author aakimov
*/
-->
<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="custom_field" type="string" />
</extension_attributes>
</config>
This will add an extension attribute to address model on backend side. Extension attributes are one of the extension points that Magento provides.
To access your data on backend you can use:
// Magento will generate interface that includes your custom attribute
$value = $address->getExtensionAttributes()->getCustomField();
Hope, this helps and will be added to official documentation.