Magento 2 - Как добавить настраиваемое поле для оформления заказа и затем отправить его


49

Все учебники охватывают только добавление полей, но при сохранении значения этих полей пропускается #mindblown. Я не знаю почему, это самая важная часть добавления любого поля или формы.

Я пытался следовать документации Magento , но ... это отстой.

В целях тестирования я пытаюсь добавить другие поля к адресу доставки, просто игнорируя настраиваемые области, настраиваемые наборы данных, настраиваемые поставщики данных и другие недокументированные вещи, что выглядит слишком странно для меня.

Я понятия не имею, что означает, что форма "статическая" или "динамическая". Для меня все формы оформления заказа динамически строятся поверх шаблонов KnockoutJS, но ... когда я пытаюсь "статичным" способом, я могу добавить сюда входные данные (так что это статическая форма или нет?).

Сначала я пытаюсь выяснить, почему наблюдаемые объекты Knockout просто игнорируют мои поля во время анализа и отправки данных. Я обнаружил, что в моих полях есть пустой nameпараметр, но я не могу найти способ исправить эту проблему. IMO, он должен быть передан компоненту рендеринга UI через inputNameпараметр, так же как и любые другие параметры, такие как disabledи placeholderт.д.

Во-вторых, я попытался использовать «динамический» способ создания плагина с LayoutProcessorпередачей точно таких же данных ... и теперь у меня есть поля с names, но отправка по-прежнему не работает вообще.

После изучения JS я обнаружил, что подготовка этого запроса ведется в module-checkout/view/frontend/web/js/model/shipping-save-processor/default.jsфайле, который зависит от того, module-checkout/view/frontend/web/js/model/quote.jsгде определены / созданы наблюдаемые Knockout.

Каким-то образом 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 выглядит странно для меня)
  • Как отправить значения полей, не связанных с новыми адресами? Я не видел подобной конфигурации нигде. В моем случае я хотел бы отправить комментарий заказа (textarea) и запрос счета (флажок). Оба не должны быть сохранены как адреса, т.к. некоторые пользователи могут захотеть сохранить этот адрес для будущего использования.
  • Есть ли документация о «статических» и «динамических» формах или некоторые примеры / сравнения? Стоит думать об этом так?

Дополнительный экзистенциальный вопрос:

  • Почему это так противоречиво? Почему я должен определить тонны параметров в файлах XML / PHP, в то время как Magento вообще может только визуализировать входные данные, а затем я должен обрабатывать все самостоятельно?

3
Magento Devdocs недавно добавил несколько новых документов об использовании компонентов пользовательского интерфейса. На самом деле, мы находимся в процессе написания нового руководства ... но у нас еще есть пути. Пожалуйста, посмотрите на devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html . К сожалению, мы еще не завершили темы об источниках данных, что, как вам кажется, вам больше всего нужно. В потоке конфигурации с использованием компонентов пользовательского интерфейса есть раздел, который может помочь. Я постараюсь найти больше ответов.
Tanberry 13.09.16

Почему это должно быть кошмарным добавлением простого поля на кассе? Я просто не могу понять. И почти все так сложно
slayerbleast

@slayerbleast Мир меняется, рендеринг на стороне сервера умирает. Так что все по-другому, не сложнее без какой-либо причины.
igloczek

Ответы:


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. PHP-код, который вставляет дополнительное поле в 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;

Как я уже упоминал, это добавит ваше поле к customAttributesсвойству объекта адреса JS. Это свойство было разработано, чтобы содержать пользовательские атрибуты адресов EAV и связано с \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributesметодом.

Приведенный выше код автоматически обрабатывает постоянство локального хранилища на веб-интерфейсе. Вы можете получить значение поля из локального хранилища, используя checkoutData.getShippingAddressFromData()(где checkoutDataесть Magento_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. Создайте ваше имя_модуля / 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. Создайте имя_модуля / 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

Пожалуйста, смотрите мой обновленный ответ выше;)
Аакимов

4
Официальный документ на эту тему уже доступен! devdocs.magento.com/guides/v2.1/howdoi/checkout/…
Алекс

1
Нужен ли дополнительный шаг для сохранения значений по заказу?
Алекс Хэдли

Я думаю, что если у вас есть статическая форма, лучше вставить поле в LayoutProcessor через XML, как в этом примере: devdocs.magento.com/guides/v2.1/howdoi/checkout/…
cjohansson

-1

По моему опыту, m2 использует xml для определения таких компонентов, как поля и т. Д. Это помогает при отладке, упрощает взаимодействие с данными. В поле front-enders вы должны попытаться переопределить шаблоны оформления заказа и добавить туда свои собственные поля. С помощью KO вы сможете работать и связывать данные из внешнего интерфейса и внутреннего интерфейса.


4
Это неправильный совет, шаблоны ч / б оформления не содержат и не должны содержать поля ввода, добавленные вручную. Мы должны использовать KO для рендеринга шаблонов в выбранных регионах (все построено с использованием компонентов пользовательского интерфейса)
igloczek

Не могли бы вы поделиться примером добавления пользовательских компонентов пользовательского интерфейса в веб-интерфейс?
mrtuvn

Как говорит @igloczek Это неправильный совет, потому что шаблоны оформления заказа никогда не должны содержать поля ввода, добавленные вручную.
diazwatson
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.