Magento 2 - Come aggiungere un campo personalizzato al checkout e quindi inviarlo


49

Tutti i tutorial riguardano solo l'aggiunta di un campo, ma il salvataggio del valore di questo file viene ignorato #mindblown. Non so perché, è la parte più importante dell'aggiunta di qualsiasi campo o modulo.

Ho provato a seguire i documenti di Magento , ma ... fa schifo.

A scopo di test, provo ad aggiungere altri campi all'indirizzo di spedizione, solo per ignorare gli ambiti personalizzati, i set di dati personalizzati, i fornitori di dati personalizzati e altre cose prive di documenti, il che mi sembra troppo strano.

Non ho idea di cosa significhi che la forma è "statica" o "dinamica". Per me tutti i moduli di checkout sono costruiti dinamicamente in cima ai modelli KnockoutJS, ma ... quando provo il modo "statico", sono in grado di aggiungere input qui (quindi è un modulo statico o no?).

Per prima cosa provo a eseguire il debug del motivo per cui gli osservabili Knockout ignorano i miei campi durante l'analisi e l'invio dei dati. Ho scoperto che i miei campi hanno un nameparametro vuoto , ma non riesco a gestire un modo per risolvere questo problema. IMO dovrebbe essere passato al renderer del componente UI tramite inputNameparametro, lo stesso di qualsiasi altra opzione come disabled, placeholderecc. (Altri parametri funzionano bene, ho controllato la configurazione generata dal mio XML per inizializzare il modulo di checkout e mi sembra buono)

In secondo luogo ho provato a usare il modo "dinamico" con la creazione di plugin con LayoutProcessore il passaggio esattamente degli stessi dati ... e ora ho campi con names, ma l'invio non funziona affatto.

Dopo aver scavato in JS ho scoperto che la preparazione di questa richiesta è mantenuta in module-checkout/view/frontend/web/js/model/shipping-save-processor/default.jsarchivio, che dipende da module-checkout/view/frontend/web/js/model/quote.jsdove sono definiti / creati gli osservabili Knockout.

In qualche modo module-checkout/view/frontend/web/js/model/address-converter.jsaggiorno questo osservabile e dipende da module-checkout/view/frontend/web/js/model/new-customer-address.js, dove ho finalmente trovato alcune interessanti opzioni di configurazione - elenco di tutti i campi degli indirizzi.

Quando aggiungo i miei campi qui, gli script iniziano ad analizzare e a inviarli, OFC ottengo 500, il backend b / c non li riconosce ... (non chiedere, non sono uno sviluppatore di backend)

Quindi ecco le mie domande:

  • È un modo giusto per gestire questo tipo di personalizzazione? (b / c sembra strano per me)
  • Come inviare valori di campi non correlati a nuovi indirizzi? Non ho visto una configurazione simile da nessuna parte. Nel mio caso, desidero inviare il commento dell'ordine (textarea) e la richiesta di fattura (casella di controllo). Entrambi non dovrebbero essere salvati come indirizzo, b / c alcuni utenti potrebbero voler salvare questo indirizzo per uso futuro.
  • Esiste una documentazione sui moduli "statici" e "dinamici" o alcuni esempi / confronti? Vale la pena pensarci in questo modo?

Domanda esistenziale aggiuntiva:

  • Perché questo è così incoerente? Perché devo definire tonnellate di parametri nei file XML / PHP, mentre Magento può solo rendere un input e quindi devo gestire tutto da solo?

3
Magento Devdocs ha recentemente aggiunto alcuni nuovi documenti sull'utilizzo dei componenti dell'interfaccia utente. In realtà stiamo scrivendo una nuova guida ... ma abbiamo ancora molta strada da fare. Dai un'occhiata a devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html . Sfortunatamente, non abbiamo ancora completato gli argomenti sulle fonti di dati, che è ciò di cui hai maggiormente bisogno. C'è un argomento sul flusso di configurazione che utilizza i componenti dell'interfaccia utente, che potrebbe essere d'aiuto. Lavorerò per trovare più risposte.
tanberry,

Perché deve essere un incubo aggiungere un semplice campo alla cassa? Non riesco proprio a capire. E quasi tutto è così difficile
slayerbleast

@slayerbleast World sta cambiando, il rendering sul lato server sta morendo. Quindi è diverso, non più difficile senza alcun motivo.
igloczek,

Risposte:


55

Proverò a rispondere alle tue domande.

  1. No . Questo non è un modo corretto per aggiungere attributi personalizzati al modulo dell'indirizzo di spedizione. Non è necessario modificare new-customer-address.js. In effetti, questo file JS elenca tutti gli attributi di indirizzo predefiniti e corrisponde all'interfaccia di back-end corrispondente, \Magento\Quote\Api\Data\AddressInterfacema Magento offre la possibilità di passare qualsiasi attributo personalizzato al back-end senza modificare i componenti di back-end / front-end .

    Il componente JS menzionato ha customAttributesproprietà. I tuoi attributi personalizzati saranno gestiti automaticamente se il loro $dataScopePrefixè ' shippindAddress.custom_attributes'.

  2. Se ho compreso correttamente la tua domanda, hai dati che non fanno parte dell'indirizzo del cliente ma devi inviarlo anche al back-end. La risposta a questa domanda è:

    Dipende . Ad esempio, puoi scegliere il seguente approccio: aggiungi un modulo personalizzato alla pagina di checkout che include tutti i campi extra (like comment, invoice request etc) , aggiungi la logica JS che gestirà questo modulo in base ad alcuni eventi e fornirà un servizio personalizzato che riceverà i dati dal frontend e dall'archivio da qualche parte per un uso futuro.

  3. Tutta la documentazione ufficiale relativa al checkout si trova all'indirizzo http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html . Il termine statico si riferisce ai moduli in cui tutti i campi sono già noti / predefiniti (ad esempio: il modulo avrà sempre 2 campi di testo con etichette predefinite) e non può cambiare in base ad alcune impostazioni nel back-end.

    Tali moduli possono essere dichiarati usando layout XML configuration. D'altra parte, il termine dinamico si riferisce a moduli il cui set di campi può cambiare (ad esempio: il modulo di checkout può avere più / meno campi in base alle impostazioni di configurazione).

    In questo caso, l'unico modo per dichiarare tale modulo è utilizzare il LayoutProcessorplugin.

  4. :) Magento cerca di coprire il maggior numero possibile di casi d'uso che possono essere significativi per i commercianti durante l'uso / la personalizzazione di Magento possibile. A volte questo porta alla situazione in cui alcuni casi d'uso semplici diventano più complessi.

Spero che sia di aiuto.

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

OK ... Consente di scrivere del codice;)

  1. Codice PHP che inserisce un campo aggiuntivo 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;

Come ho già detto, questo aggiungerà il tuo campo alla customAttributesproprietà dell'oggetto indirizzo JS. Questa proprietà è stata progettata per contenere attributi di indirizzi EAV personalizzati ed è correlata al \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributesmetodo.

Il codice sopra gestirà automaticamente la persistenza della memoria locale sul frontend. È possibile ottenere il valore del campo dalla memoria locale utilizzando checkoutData.getShippingAddressFromData()(dove si checkoutDatatrova Magento_Checkout/js/checkout-data).

  1. Aggiungi mixin per modificare il comportamento di "Magento_Checkout / js / action / set-shipping-information" (questo componente è responsabile dell'invio dei dati tra i passaggi di checkout di fatturazione e spedizione)

========

2.1. Creareyour_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. Crea 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. Crea il tuo nome_modulo / 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>

Ciò aggiungerà un attributo di estensione per indirizzare il modello sul lato back-end. Gli attributi di estensione sono uno dei punti di estensione forniti da Magento. Per accedere ai tuoi dati sul backend puoi usare:

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

Spero che questo aiuti e sarà aggiunto alla documentazione ufficiale.


Grazie per la risposta Alex! Ci ho provato custom_attributes, ma per me non funziona. Ecco come appare parte di LayoutProcessor.php` - gist.github.com/Igloczek/eaf4d2d7a0a04bd950110296ec3f7727 Ma shipping-info o anche localStorage checkout-datanon contiene affatto questi dati.
igloczek,

Si prega di vedere la mia risposta aggiornata sopra;)
aakimov

4
Il documento ufficiale su questo argomento è già disponibile! devdocs.magento.com/guides/v2.1/howdoi/checkout/…
Alex

1
È necessario un ulteriore passaggio per salvare i valori rispetto all'ordine?
Alex Hadley,

Penso che se hai una forma statica, è meglio inserire un campo in LayoutProcessor tramite XML come in questo esempio: devdocs.magento.com/guides/v2.1/howdoi/checkout/…
cjohansson

-1

Nella mia esperienza, m2 usa xml per definire componenti come campi ecc. È di aiuto per il debug, interattivo con i dati più facili. Sul campo dei front-end dovresti provare a sovrascrivere i modelli di checkout e aggiungere i tuoi campi personalizzati. Con KO ti aiuta a lavorare e associare i dati da frontend e backend


4
È un consiglio sbagliato, i modelli di checkout in b / c non contengono e non devono mai contenere campi di input aggiunti manualmente. Dobbiamo usare KO per eseguire il rendering di modelli in aree selezionate (tutto viene creato utilizzando i componenti dell'interfaccia utente)
igloczek,

Potresti condividere un esempio di aggiungere ui-componenti di campo personalizzati in frontend?
mrtuvn,

Come dice @igloczek È un consiglio sbagliato, perché i modelli di checkout non devono mai contenere campi di input aggiunti manualmente.
diazwatson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.