Magento 2-如何将自定义字段添加到结帐并发送


49

所有教程都只涉及添加字段,但是该文件的保存值被跳过#mindblown。我不知道为什么,这是添加任何字段或表单的最重要部分。

我尝试关注Magento文档,但是...太糟了。

出于测试目的,我尝试将其他字段添加到收货地址,只是忽略自定义范围,自定义数据集,自定义数据提供程序和其他未记录的内容,这对我来说太奇怪了。

我不知道这种形式是“静态”还是“动态”。对我来说,所有结帐表单都是在KnockoutJS模板之上动态构建的,但是...当我尝试“静态”方式时,我可以在此处添加输入(所以它是静态表单还是不是静态表单?)。

首先,我尝试调试为什么Knockout可观察对象在解析和发送数据时只会忽略我的字段。我发现我的字段的name参数为空,但是我无法解决此问题。IMO应该通过inputName参数将其传递给UI组件渲染器,与其他任何选项(例如disabledplaceholder等等)相同(其他参数工作正常,我检查了从XML生成的配置,以检出模块初始化,对我来说很不错)

其次,我尝试使用“动态”方式来创建插件LayoutProcessor并传递完全相同的数据……现在我具有names 字段,但是发送仍然根本不起作用。

深入研究JS之后,我发现准备此请求的内容保存在module-checkout/view/frontend/web/js/model/shipping-save-processor/default.js文件中,具体取决于在module-checkout/view/frontend/web/js/model/quote.js哪里定义/创建了可观察的观察项。

我终于以某种方式module-checkout/view/frontend/web/js/model/address-converter.js更新了这个可观察变量,并依赖于module-checkout/view/frontend/web/js/model/new-customer-address.js,在那里我终于找到了一些有趣的配置选项-所有地址字段的列表。

当我在此处添加字段时,脚本开始解析并发送它们,OFC得到500,b / c后端无法识别它们……(不要问,我不是后端开发人员)

所以这是我的问题:

  • 这是处理这种类型的自定义的正确方法吗?(b / c对我来说很奇怪)
  • 如何发送与新地址无关的字段的值?我在任何地方都没有看到类似的配置。就我而言,我想发送订单注释(文本区域)和发票请求(复选框)。两者都不应该另存为地址,有些用户可能想要保存此地址以备将来使用。
  • 是否有关于“静态”和“动态”表格的文档或一些示例/比较?值得这样思考吗?

附加的存在性问题:

  • 为什么如此不一致?为什么我必须在XML / PHP文件中定义大量参数,而Magento根本只能呈现输入,然后我必须自己处理所有事情?

3
Magento Devdocs最近添加了一些有关使用UI组件的新文档。实际上,我们正在编写一本全新的指南...但是还有路要走。请查看devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html。不幸的是,我们尚未完成有关数据源的主题,这听起来似乎是您最需要的。有关使用UI组件的配置流程的主题,这可能会有所帮助。我将努力寻找更多答案。
tanberry

为什么在结帐时添加一个简单字段会成为一场噩梦?我根本听不懂。几乎所有事情都如此艰难
-slayerbleast

@slayerbleast世界正在发生变化,服务器端渲染正在逐渐消失。所以这是不同的,没有任何理由就不难了。
igloczek

Answers:


55

我会尽力回答您的问题。

  1. 没有。这不是将自定义属性添加到收货地址表单的正确方法。您无需进行编辑new-customer-address.js。实际上,此JS文件列出了所有预定义的地址属性并匹配了相应的后端接口,\Magento\Quote\Api\Data\AddressInterface但是Magento提供了将任何自定义属性传递给后端的功能,而无需修改后端/前端组件。

    提到的JS组件具有customAttributes属性。如果您的自定义属性$dataScopePrefix为“ shippindAddress.custom_attributes”,则会自动处理。

  2. 如果我正确理解了您的问题,则您的数据不是客户地址的一部分,但您也需要将其发送到后端。这个问题的答案是:

    这要看情况。例如,您可以选择以下方法:将自定义表单添加到包括所有额外字段的结帐页面 (like comment, invoice request etc),添加将基于某些事件处理该表单的JS逻辑,并提供将接收来自前端的数据并存储的自定义服务它在某个地方以备将来使用。

  3. 与结帐有关的所有官方文档都位于http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html术语“静态”是指所有字段都是已知/预定义的表单(例如:表单将始终具有2个带有预定义标签的文本字段),并且不能根据后端中的某些设置进行更改。

    可以使用声明这种形式layout XML configuration。另一方面,术语“动态”是指其字段集可以更改的表单(例如:根据配置设置,结帐表单可以具有更多/更少的字段)。

    在这种情况下,声明这种形式的唯一方法是使用LayoutProcessor插件。

  4. :) Magento尝试涵盖尽可能多的用例,这些用例对Magento使用/定制期间的商家而言可能意义重大。有时,这会导致某些简单用例变得更加复杂的情况。

希望这可以帮助。

================================================== =======================

好吧 ...让我们写一些代码;)

  1. 在LayoutProcessor中插入其他字段的PHP代码

========

/**
 * @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;

如前所述,这会将您的字段添加到customAttributesJS地址对象的属性中。此属性旨在包含自定义的EAV地址属性,并且与\Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributes方法有关。

上面的代码将自动处理前端的本地存储持久性。您可以通过从本地存储让您的字段值checkoutData.getShippingAddressFromData()(如果checkoutDataMagento_Checkout/js/checkout-data)。

  1. 添加mixin来更改“ Magento_Checkout / js / action / set-shipping-information”的行为(此组件负责在运输和结算结帐步骤之间提交数据)

========

2.1。创造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。创建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();
        });
    };
});
  1. 创建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>

这会将扩展属性添加到后端的地址模型。扩展属性是Magento提供的扩展点之一。要在后端访问数据,您可以使用:

// Magento will generate interface that includes your custom attribute
$value = $address->getExtensionAttributes()->getCustomField();

希望这会有所帮助,并将被添加到官方文档中。


感谢您的回答亚历克斯!我尝试了custom_attributes方法,但对我不起作用。这就是LayoutProcessor.php`的一部分的样子-gist.github.com/Igloczek/eaf4d2d7a0a04bd950110296ec3f7727但是shipping-info ,甚至localStorage checkout-data根本不包含此数据。
igloczek

请在上方查看我更新的答案;)
aakimov

4
有关此主题的官方文档已经可用!devdocs.magento.com/guides/v2.1/howdoi/checkout/…–
亚历克斯

1
是否需要采取额外的步骤来保存针对订单的值?
亚历克斯·哈德利

我认为,如果您有静态表单,则最好像下面的示例一样通过XML将字段插入LayoutProcessor:devdocs.magento.com/guides/v2.1/howdoi/checkout/…–
cjohansson

-1

以我的经验,m2使用xml定义字段等组件。这对调试很有帮助,与数据的交互更加容易。在前者字段上,您应该尝试覆盖结帐模板,并在其中添加自己的自定义字段。借助KO,您可以处理和绑定前端和后端的数据


4
这是错误的建议,B / C结帐模板不包含,也不应包含手动添加的输入字段。我们必须使用KO在选定区域中渲染模板(所有内容都使用UI组件
构建

您能否分享在前端添加自定义字段ui组件的示例?
mrtuvn

正如@igloczek所说,这是错误的建议,因为结帐模板永远都不应包含手动添加的输入字段。
diazwatson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.