Magento 2 - So fügen Sie ein benutzerdefiniertes Feld zum Auschecken hinzu und senden es dann

49

In allen Tutorials wird nur das Hinzufügen von Feldern behandelt. Das Speichern des Werts dieser Dateien wird jedoch übersprungen. Ich weiß nicht warum, es ist der wichtigste Teil beim Hinzufügen von Feldern oder Formularen.

Ich habe versucht, Magento-Dokumenten zu folgen , aber ... es ist scheiße.

Zu Testzwecken versuche ich, der Lieferadresse weitere Felder hinzuzufügen, nur um benutzerdefinierte Bereiche, benutzerdefinierte Datensätze, benutzerdefinierte Datenanbieter und andere undokumentierte Dinge zu ignorieren, was für mich zu seltsam aussieht.

Ich habe keine Ahnung, was bedeutet, dass diese Form "statisch" oder "dynamisch" ist. Für mich werden alle Checkout-Formulare dynamisch über KnockoutJS-Vorlagen erstellt, aber ... wenn ich es auf "statische" Weise versuche, kann ich hier Eingaben hinzufügen (also handelt es sich um ein statisches Formular oder nicht?).

Zuerst versuche ich zu debuggen, warum Knockout-Observables meine Felder beim Parsen und Senden von Daten einfach ignorieren. Ich habe festgestellt, dass meine Felder leere nameParameter enthalten, kann dieses Problem jedoch nicht beheben. IMO sollte es UI - Komponente Renderer über geben werden inputNameParameter, wie alle anderen Optionen wie disabled, placeholderusw. (andere Parameter funktioniert gut, ich überprüft Konfiguration erzeugt von meinem XML zur Kasse Modulinitialisierung und sieht gut aus für mich)

Zweitens habe ich versucht, "dynamisch" zu arbeiten, indem ich Plugins mit LayoutProcessordenselben Daten erstellte und diese weitergab ... und jetzt habe ich Felder mit names, aber das Senden funktioniert überhaupt nicht.

Nachdem ich mich in JS vertieft hatte, stellte ich fest, dass die Vorbereitung dieser Anfrage in einer module-checkout/view/frontend/web/js/model/shipping-save-processor/default.jsDatei gespeichert ist, die davon abhängt, module-checkout/view/frontend/web/js/model/quote.jswo Knockout-Observables definiert / erstellt werden.

Irgendwie module-checkout/view/frontend/web/js/model/address-converter.jsaktualisieren diese Observables und hängen davon ab module-checkout/view/frontend/web/js/model/new-customer-address.js, wo ich endlich einige interessante Konfigurationsmöglichkeiten gefunden habe - Liste aller Adressfelder.

Wenn ich meine Felder hier hinzufüge, fangen die Skripte an, sie zu analysieren und zu senden. OFC, ich erhalte 500, das b / c-Backend erkennt sie nicht ... (nicht fragen, ich bin kein Backend-Entwickler)

Hier kommen meine Fragen:

  • Es ist eine richtige Art, mit dieser Art von Anpassung umzugehen? (B / C sieht komisch aus für mich)
  • Wie werden Werte von Feldern gesendet, die sich nicht auf neue Adressen beziehen? Ich habe nirgendwo eine ähnliche Konfiguration gesehen. In meinem Fall möchte ich einen Bestellkommentar (Textbereich) und eine Rechnungsanfrage (Kontrollkästchen) senden. Beides sollte nicht als Adresse gespeichert werden, b / c einige Benutzer möchten diese Adresse möglicherweise für die zukünftige Verwendung speichern.
  • Gibt es eine Dokumentation über "statische" und "dynamische" Formulare oder einige Beispiele / Vergleiche? Lohnt es sich so darüber nachzudenken?

Zusätzliche existenzielle Frage:

  • Warum ist das so inkonsistent? Warum muss ich Unmengen von Parametern in XML / PHP-Dateien definieren, während Magento überhaupt nur eine Eingabe rendern kann und ich dann alles selbst handhaben muss?
Igloczek
quelle
3
Magento Devdocs hat kürzlich einige neue Dokumente zur Verwendung von UI-Komponenten hinzugefügt. Wir sind gerade dabei, einen komplett neuen Leitfaden zu schreiben ... aber wir haben noch einen weiten Weg vor uns. Bitte werfen Sie einen Blick auf devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html . Leider haben wir die Themen zu Datenquellen noch nicht abgeschlossen. Es gibt ein Thema zum Konfigurationsablauf unter Verwendung von UI-Komponenten, das möglicherweise hilfreich ist. Ich werde daran arbeiten, mehr Antworten zu finden.
Tanberry
Warum muss es ein Albtraum sein, an der Kasse ein einfaches Feld hinzuzufügen? Ich kann es einfach nicht verstehen. Und fast alles ist so schwer
Jägergott
@slayerbleast World verändert sich, serverseitiges Rendern im Sterben. Also ist es anders, nicht ohne Grund schwieriger.
Igloczek

Antworten:

55

Ich werde versuchen, Ihre Frage (n) zu beantworten.

  1. Nein . Dies ist keine korrekte Methode, um benutzerdefinierte Attribute zum Versandadressformular hinzuzufügen. Sie müssen nicht bearbeiten new-customer-address.js. In der Tat listet diese JS-Datei alle vordefinierten Adressattribute auf und stimmt mit der entsprechenden Backend-Schnittstelle überein. \Magento\Quote\Api\Data\AddressInterfaceMagento bietet jedoch die Möglichkeit, benutzerdefinierte Attribute an das Backend zu übergeben, ohne die Backend- / Frontend- Komponenten zu ändern .

    Die erwähnte JS-Komponente hat eine customAttributesEigenschaft. Ihre benutzerdefinierten Attribute werden automatisch verarbeitet, wenn sie $dataScopePrefix" shippindAddress.custom_attributes" lauten .

  2. Wenn ich Ihre Frage richtig verstanden habe, haben Sie Daten, die nicht Teil der Kundenadresse sind, aber Sie müssen sie auch an das Backend senden. Die Antwort auf diese Frage lautet:

    Kommt drauf an . Sie können beispielsweise den folgenden Ansatz wählen: Hinzufügen eines benutzerdefinierten Formulars zur Checkout-Seite, die alle Ihre zusätzlichen Felder enthält (like comment, invoice request etc) , Hinzufügen einer JS-Logik, die dieses Formular basierend auf einigen Ereignissen verarbeitet, und Bereitstellen eines benutzerdefinierten Diensts, der die Daten vom Frontend und vom Store empfängt es irgendwo für die zukünftige Verwendung.

  3. Die gesamte offizielle Dokumentation zum Checkout finden Sie unter http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html . Der Begriff statisch bezieht sich auf Formulare, bei denen alle Felder bereits bekannt / vordefiniert sind (zum Beispiel: Formular enthält immer 2 Textfelder mit vordefinierten Bezeichnungen) und kann aufgrund einiger Einstellungen im Backend nicht geändert werden.

    Solche Formulare können mit deklariert werden layout XML configuration. Andererseits bezieht sich der Begriff "dynamisch" auf Formulare, deren Feldsatz sich ändern kann (zum Beispiel: Checkout-Formulare können je nach Konfigurationseinstellungen mehr oder weniger Felder enthalten).

    In diesem Fall können Sie ein solches Formular nur mit dem LayoutProcessorPlugin deklarieren .

  4. :) Magento versucht, so viele Anwendungsfälle wie möglich abzudecken, die für die Händler bei der Verwendung / Anpassung von Magento von Bedeutung sein können. Dies führt manchmal zu Situationen, in denen einige einfache Anwendungsfälle komplexer werden.

Hoffe das hilft.

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

OK ... Lass uns Code schreiben;)

  1. PHP-Code, der zusätzliches Feld in LayoutProcessor einfügt

========

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

Wie bereits erwähnt, wird Ihr Feld der customAttributesEigenschaft des JS-Adressobjekts hinzugefügt . Diese Eigenschaft enthält benutzerdefinierte EAV-Adressattribute und ist \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributesmethodenbezogen.

Der obige Code behandelt automatisch die Persistenz des lokalen Speichers im Frontend. Sie können Ihren Feldwert über checkoutData.getShippingAddressFromData()(where checkoutDatais Magento_Checkout/js/checkout-data) aus dem lokalen Speicher abrufen .

  1. Füge mixin hinzu, um das Verhalten von 'Magento_Checkout / js / action / set-shipping-information' zu ändern (diese Komponente ist für die Datenübertragung zwischen Versand- und Rechnungsprüfungsschritten verantwortlich)

========

2.1. Erstellenyour_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. Erstellen Sie Ihren_Modulnamen / 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. Erstellen Sie den Modulnamen / 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>

Dadurch wird dem Adressmodell auf der Back-End-Seite ein Erweiterungsattribut hinzugefügt. Erweiterungsattribute sind einer der von Magento bereitgestellten Erweiterungspunkte. Um auf Ihre Daten im Backend zuzugreifen, können Sie Folgendes verwenden:

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

Hoffe, das hilft und wird in die offizielle Dokumentation aufgenommen.

aakimov
quelle
Danke für die Antwort Alex! Ich habe es versucht custom_attributes, aber es funktioniert nicht für mich. So sieht ein Teil von LayoutProcessor.php aus - gist.github.com/Igloczek/eaf4d2d7a0a04bd950110296ec3f7727 Aber shipping-info oder sogar localStorage checkout-dataenthält diese Daten überhaupt nicht.
Igloczek
Bitte beachten Sie meine aktualisierte Antwort oben;)
aakimov
4
Das offizielle Dokument zu diesem Thema ist bereits verfügbar! devdocs.magento.com/guides/v2.1/howdoi/checkout/…
Alex
1
Ist ein zusätzlicher Schritt erforderlich, um die Werte für die Bestellung zu speichern?
Alex Hadley
Ich glaube, wenn Sie eine statische Form haben, ist es besser, Feld über XML in LayoutProcessor einzufügen , wie in diesem Beispiel: devdocs.magento.com/guides/v2.1/howdoi/checkout/...
cjohansson
-1

Nach meiner Erfahrung verwendet m2 XML, um Komponenten wie Felder usw. zu definieren. Dies erleichtert das Debuggen und die Interaktion mit Daten. Auf Front-Ender-Feldern sollten Sie versuchen, Checkout-Vorlagen zu überschreiben und dort Ihre eigenen benutzerdefinierten Felder hinzuzufügen. Mit KO können Sie Daten vom Frontend und Backend bearbeiten und binden

mrtuvn
quelle
4
Es ist ein falscher Rat, b / c Checkout-Vorlagen enthalten keine manuell hinzugefügten Eingabefelder und sollten diese niemals enthalten. Wir müssen KO verwenden, um Vorlagen in ausgewählten Regionen zu rendern (alles wird mit UI-Komponenten erstellt)
Igloczek
Könnten Sie ein Beispiel für das Hinzufügen von benutzerdefinierten Feld-UI-Komponenten im Frontend teilen?
MrTuvn
Wie @igloczek sagt, handelt es sich um einen falschen Rat, da Checkout-Vorlagen niemals manuell hinzugefügte Eingabefelder enthalten sollten.
Diazwatson