Magento 2 - Como adicionar um campo personalizado ao checkout e enviá-lo


49

Todos os tutoriais estão cobrindo apenas a adição de campos, mas o valor de salvamento desses arquivos é ignorado #mindblown. Não sei por que, é a parte mais importante da adição de qualquer campo ou formulário.

Eu tentei seguir os documentos do Magento , mas ... é uma merda.

Para fins de teste, tento adicionar outros campos ao endereço de entrega, apenas para ignorar escopos personalizados, conjuntos de dados personalizados, provedores de dados personalizados e outras coisas não documentadas, o que parece muito estranho para mim.

Não tenho idéia do que significa que o formulário é "estático" ou "dinâmico". Para mim, todos os formulários de checkout são construídos dinamicamente sobre os modelos do KnockoutJS, mas ... quando tento o modo "estático", sou capaz de adicionar entradas aqui (por isso é um formulário estático ou não?).

Primeiro, tento depurar por que os observáveis ​​do Knockout simplesmente ignoram meus campos durante a análise e o envio de dados. Descobri que meus campos têm nameparâmetro vazio , mas não consigo gerenciar uma maneira de corrigir esse problema. Na IMO, ele deve ser passado para o renderizador do componente da interface do usuário por meio de inputNameparâmetro, o mesmo que outras opções disabled, placeholderetc. (outros parâmetros funcionam bem, verifiquei a configuração gerada a partir do meu XML para a inicialização do módulo de checkout e fica bem para mim)

Segundo, tentei usar o modo "dinâmico" com a criação de plug-in LayoutProcessore a transmissão exatamente dos mesmos dados ... e agora tenho campos com names, mas o envio ainda não funciona.

Depois de pesquisar no JS, descobri que a preparação dessa solicitação é mantida em module-checkout/view/frontend/web/js/model/shipping-save-processor/default.jsarquivo, o que depende de module-checkout/view/frontend/web/js/model/quote.jsonde os observáveis ​​do Knockout são definidos / criados.

De alguma forma, module-checkout/view/frontend/web/js/model/address-converter.jsatualizo esses observáveis ​​e depende de module-checkout/view/frontend/web/js/model/new-customer-address.jsonde finalmente encontrei algumas opções interessantes de configuração - lista de todos os campos de endereço.

Quando adiciono meus campos aqui, os scripts começam a analisar e enviá-los, OFC eu recebo 500, o back-end b / c não os reconhece ... (não pergunte, eu não sou um desenvolvedor de back-end)

Então, aqui estão minhas perguntas:

  • É uma maneira correta de lidar com esse tipo de personalização? (b / c parece estranho para mim)
  • Como enviar valores de campos não relacionados a novos endereços? Não vi configuração semelhante em nenhum lugar. No meu caso, gostaria de enviar um comentário do pedido (área de texto) e solicitação de fatura (caixa de seleção). Ambos não devem ser salvos como um endereço, porque alguns usuários podem querer salvar esse endereço para uso futuro.
  • Existe alguma documentação sobre formulários "estáticos" e "dinâmicos" ou alguns exemplos / comparação? Vale a pena pensar dessa maneira?

Pergunta existencial adicional:

  • Por que isso é tão inconsistente? Por que eu tenho que definir vários parâmetros em arquivos XML / PHP, enquanto o Magento pode apenas renderizar uma entrada e então eu tenho que lidar com tudo sozinho?

3
O Magento Devdocs adicionou recentemente alguns novos documentos sobre o uso de componentes da interface do usuário. Na verdade, estamos no processo de escrever um novo guia inteiro ... mas ainda temos um caminho a percorrer. Por favor, dê uma olhada em devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html . Infelizmente, ainda não concluímos os tópicos sobre fontes de dados, o que parece ser o que você mais precisa. Há um tópico no fluxo de configuração usando os Componentes da UI, que pode ajudar. Vou trabalhar para encontrar mais respostas.
— tanberry

Por que tem que ser um pesadelo adicionar um campo simples no checkout? Eu simplesmente não consigo entender. E quase tudo é tão difícil
— slayerbleast

@slayerbleast O mundo está mudando, a renderização do lado do servidor está morrendo. Portanto, é diferente, não é mais difícil, sem qualquer motivo.
— igloczek

Respostas:


55

Vou tentar responder às suas perguntas.

  1. Não . Esta não é uma maneira correta de adicionar atributos personalizados ao formulário de endereço de entrega. Você não precisa editar new-customer-address.js. De fato, esse arquivo JS lista todos os atributos de endereço predefinidos e corresponde à interface de back-end correspondente, \Magento\Quote\Api\Data\AddressInterfacemas o Magento fornece a capacidade de transmitir quaisquer atributos personalizados para o back-end sem modificação dos componentes de back - end / front-end .

    O componente JS mencionado possui customAttributespropriedade. Seus atributos personalizados serão manipulados automaticamente se eles $dataScopePrefixforem ' shippindAddress.custom_attributes'.

  2. Se entendi sua pergunta corretamente, você tem dados que não fazem parte do endereço do cliente, mas também precisa enviá-los para o back-end. A resposta a esta pergunta é:

    Depende . Por exemplo, você pode escolher a seguinte abordagem: adicione formulário personalizado à página de check-out que inclui todos os seus campos extras (like comment, invoice request etc) , adicione lógica JS que manipulará esse formulário com base em alguns eventos e forneça um serviço personalizado que receberá os dados do front-end e do armazenamento em algum lugar para uso futuro.

  3. Toda a documentação oficial relacionada ao checkout está localizada em http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html . O termo estático refere-se aos formulários em que todos os campos já são conhecidos / predefinidos (por exemplo: formulário sempre terá 2 campos de texto com rótulos predefinidos) e não podem ser alterados com base em algumas configurações no back-end.

    Tais formulários podem ser declarados usando layout XML configuration. Por outro lado, termo dinâmico refere-se a formulários cujo conjunto de campos pode mudar (por exemplo: o formulário de checkout pode ter mais / menos campos com base nas definições de configuração).

    Nesse caso, a única maneira de declarar esse formulário é usar o LayoutProcessorplugin.

  4. :) O Magento tenta cobrir o maior número possível de casos de uso que possam ser significativos para os comerciantes durante o uso / personalização do Magento possível. Às vezes, isso leva à situação em que alguns casos de uso simples se tornam mais complexos.

Espero que isto ajude.

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

OK ... Vamos escrever algum código;)

  1. Código PHP que insere campo adicional no 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;

Como já mencionei, isso adicionará seu campo à customAttributespropriedade do objeto de endereço JS. Esta propriedade foi projetada para conter atributos de endereço EAV personalizados e está relacionada ao \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributesmétodo

O código acima manipulará automaticamente a persistência de armazenamento local no frontend. Você pode obter o valor do seu campo no armazenamento local usando checkoutData.getShippingAddressFromData()(onde checkoutDataestá Magento_Checkout/js/checkout-data).

  1. Adicione mixin para alterar o comportamento de 'Magento_Checkout / js / action / set-shipping-information' (este componente é responsável pelo envio de dados entre as etapas de envio e cobrança do checkout)

========

2.1 Crioyour_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 Crie 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. Crie 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>

Isso adicionará um atributo de extensão ao endereço do modelo no back-end. Os atributos de extensão são um dos pontos de extensão que o Magento fornece. Para acessar seus dados no back-end, você pode usar:

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

Espero que isso ajude e será adicionado à documentação oficial.


Obrigado pela resposta Alex! Eu tentei do custom_attributesjeito, mas não funciona para mim. É assim que parte do LayoutProcessor.php` se parece - gist.github.com/Igloczek/eaf4d2d7a0a04bd950110296ec3f7727 Mas shipping-info ou mesmo localStorage checkout-datanão contém esses dados.
— igloczek

Por favor, veja minha resposta atualizada acima;)
— aakimov 16/16

4
O documento oficial sobre este tópico já está disponível! devdocs.magento.com/guides/v2.1/howdoi/checkout/…
— Alex

11
Existe uma etapa extra necessária para que os valores sejam salvos no pedido?
— Alex Hadley

Eu acho que se você tiver um formulário estático, é melhor inserir um campo no LayoutProcessor via XML, como neste exemplo: devdocs.magento.com/guides/v2.1/howdoi/checkout/…
— cjohansson

-1

Na minha experiência, o m2 usa xml para definir componentes como campos, etc. É uma ajuda para depuração, interativa com os dados mais fácil. No campo de front-end, você deve tentar substituir os modelos de check-out e adicionar seus próprios campos personalizados. Com o KO, você pode trabalhar e vincular dados de front-end e back-end


4
É um conselho errado, os modelos de check-out b / c não contêm e nunca devem conter campos de entrada adicionados manualmente. Temos que usar KO para tornar modelos em regiões selecionadas (tudo é edificada usando componentes de UI)
— igloczek

Você poderia compartilhar um exemplo de adicionar componentes de interface do usuário de campo personalizado no front-end?
— mrtuvn 13/09/16

Como @igloczek diz: é um conselho errado, porque os modelos de checkout nunca devem conter campos de entrada adicionados manualmente.
— Diazwatson #
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.