Checkout-Formular - Wie man mehrere Elemente in einer Klasse umschließt - Magento 2


13

Wie binde ich zwei Checkout-Formularelemente in ein div ein?

Nehmen wir zum Beispiel an, ich wollte diese Felder für Land und Postleitzahl in ein div mit der Klasse von einschließen. example-classWie würde ich das tun?

Bildbeschreibung hier eingeben

Was ich probiert habe

Ich habe versucht, dies zu erreichen, indem ich sie als Kinder von hinzufügte, <item name="shippingAddress" xsi:type="array">aber das verursacht nur Fehler im Frontend. Obwohl ich eine leere Texteingabe ohne Beschriftung erhalten habe, .example-classgab es Fehler im Frontend.

Der Fehler: Cannot read property 'indexedOptions' of undefined

Das ist mein schneller Versuch:

Magento_Checkout / web / template / versandadresse / form.html

<div id="shipping-new-address-form" class="fieldset address">
    <div class="testing">
        <!-- ko foreach: getRegion('example-class') -->
        <!-- ko template: getTemplate() --><!-- /ko -->
        <!--/ko-->
    </div>
    <!-- ko foreach: getRegion('additional-fieldsets') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
    <!--/ko-->
</div>

checkout_index_index.xml

<item name="example-for-adding-class" xsi:type="array">
    <item name="component" xsi:type="string">uiComponent</item>
    <item name="config" xsi:type="array">
        <item name="deps" xsi:type="array">
            <item name="0" xsi:type="string">checkoutProvider</item>
        </item>
    </item>
    <item name="displayArea" xsi:type="string">example-class</item>
    <item name="children" xsi:type="array">
        <!-- The following items override configuration of corresponding address attributes -->
        <item name="region" xsi:type="array">
            <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field -->
            <item name="visible" xsi:type="boolean">false</item>
        </item>
        <item name="region_id" xsi:type="array">
            <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item>
            <item name="config" xsi:type="array">
                <item name="template" xsi:type="string">ui/form/field</item>
                <item name="elementTmpl" xsi:type="string">ui/form/element/select</item>
                <item name="customEntry" xsi:type="string">shippingAddress.region</item>
            </item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
            <!-- Value of region_id field is filtered by the value of county_id attribute -->
            <item name="filterBy" xsi:type="array">
                <item name="target" xsi:type="string"><![CDATA[${ $.provider }:${ $.parentScope }.country_id]]></item>
                <item name="field" xsi:type="string">country_id</item>
            </item>
        </item>
        <item name="postcode" xsi:type="array">
            <!-- post-code field has custom UI component -->
            <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item>
            <item name="sortOrder" xsi:type="string">2</item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="string">true</item>
            </item>
        </item>
        <item name="country_id" xsi:type="array">
            <item name="sortOrder" xsi:type="string">1</item>
        </item>
    </item>
</item>

Es muss einen einfacheren Weg geben, entweder fehlt mir etwas, oder das ist die Definition von Überentwicklung. Das Hinzufügen eines Divs über zwei Elemente sollte niemals so schwierig sein.

Antworten:


14

Sehr interessante Frage. Lassen Sie mich die letzte Annahme zur Checkout-Implementierung beantworten. Es könnte ein bisschen überarbeitet sein, da Sie mehr als nur 1 Änderung in 1 Datei hinzufügen müssen.

Für diesen Ansatz sind keine Änderungen an den Magento 2-Kernmodulen erforderlich.

Um Ihr Ziel zu erreichen und die Versandadressfelder der Kasse in ein benutzerdefiniertes Element zu packen, sollten die folgenden Elemente hinzugefügt werden:

  1. Benutzerdefinierte Datei checkout_index_index.xml mit der neuen Definition der Benutzeroberflächenkomponente
  2. Neue HTML-Vorlage mit benutzerdefiniertem Element
  3. Layout Prozessor Plugin
  4. Die di.xml-Deklaration für das neue Plugin

Die Datei Custom_Checkout \ view \ frontend \ layout \ checkout_index_index.xml :

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
    <referenceBlock name="checkout.root">
        <arguments>
            <argument name="jsLayout" xsi:type="array">
                <item name="components" xsi:type="array">
                    <item name="checkout" xsi:type="array">
                        <item name="children" xsi:type="array">
                            <item name="steps" xsi:type="array">
                                <item name="children" xsi:type="array">
                                    <item name="shipping-step" xsi:type="array">
                                        <item name="children" xsi:type="array">
                                            <item name="shippingAddress" xsi:type="array">
                                                <item name="children" xsi:type="array">
                                                    <item name="shipping-address-fieldset" xsi:type="array">
                                                        <item name="children" xsi:type="array">
                                                            <item name="custom-field-group" xsi:type="array">
                                                                <item name="component" xsi:type="string">uiComponent</item>
                                                                <item name="sortOrder" xsi:type="string">0</item>
                                                                <item name="template" xsi:type="string">Custom_Checkout/checkout/field-group</item>
                                                                <item name="children" xsi:type="array">
                                                                    <item name="field-group" xsi:type="array">
                                                                        <item name="component" xsi:type="string">uiComponent</item>
                                                                        <item name="displayArea" xsi:type="string">field-group</item>
                                                                    </item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </item>
            </argument>
        </arguments>
    </referenceBlock>
</body>

Im Layout sollten wir eine neue Benutzeroberflächenkomponente für benutzerdefinierte Feldgruppen hinzufügen . Die Komponente verfügt über eine eigene Vorlage Custom_Checkout \ view \ web \ template \ checkout \ field-group.html, in der alle Felder gerendert werden. Außerdem hat die benutzerdefinierte Feldgruppenkomponente den Wert "0" für den sortOrder- Knoten. Sie können die Komponente rendern, bevor alle Felder als Teil der Komponente " Lieferadresse-Feldsatz" deklariert werden.

Es gibt auch eine Feldgruppen - UI-Komponente mit einer eigenen displayArea- Einstellung.

Die Vorlagendatei Custom_Checkout \ view \ web \ template \ checkout \ field-group.html :

<div class="custom">
<!-- ko foreach: getRegion('field-group') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>

Die Matrize erlaubt es, alle Komponenten in die Rendering hinzugefügt Feldgruppe Region (auch bekannt als displayArea ).

Die Klassendatei Custom \ Checkout \ Plugin \ AddressLayoutProcessor :

namespace Custom\Checkout\Plugin;

use Magento\Checkout\Block\Checkout\LayoutProcessor;

/**
 * Class AddressLayoutProcessor
 */
class AddressLayoutProcessor
{
    /**
     * @param LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */
    public function afterProcess(LayoutProcessor $subject, array $jsLayout)
    {
        $fieldGroup = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
            ['children']['shippingAddress']['children']['shipping-address-fieldset']
            ['children']['custom-field-group']['children']['field-group']['children'];

        $shippingAddressFields = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
            ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];

        $fieldGroup['country_id'] = $shippingAddressFields['country_id'];
        $fieldGroup['postcode'] = $shippingAddressFields['postcode'];

        $shippingAddressFields['country_id']['visible'] = false;
        $shippingAddressFields['postcode']['visible'] = false;

        return $jsLayout;
    }
}

Die Klasse ist dafür verantwortlich, sowohl die country_id- als auch die postcode- Feldkonfiguration in die neu erstellte benutzerdefinierte Feldgruppenkomponente zu kopieren .

Die Felder, die der benutzerdefinierten Feldgruppe zugewiesen wurden, sollten als ausgeblendet (sichtbar = wahr) markiert werden, um Doppelungen beim Rendern zu vermeiden. Die KomponenteDisabled sollte nicht zum Deaktivieren von country_id und postcode verwendet werden, da andere Abhängigkeiten (z. B. die Datei region.js) und der Mechanismus zur Verarbeitung der Versandadresse vorliegen.

Die Datei Custom \ Checkout \ etc \ frontend \ di.xml :

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
        <plugin name="customFieldGroupPlugin" type="Custom\Checkout\Plugin\AddressLayoutProcessor"/>
    </type>
</config>

Der Plugin-Ansatz für die Felder ändert sich, da Felder mit vollständiger Konfiguration kopiert werden sollten. Wenn der Layout-Prozessor in einem benutzerdefinierten Modul deklariert ist, fängt das Plugin Änderungen ab.

Infolgedessen werden sowohl das Feld country_id als auch das Feld postcode im Versandadressenformular gerendert und wie folgt in das benutzerdefinierte Element eingeschlossen (ich habe einige Stile für die benutzerdefinierte CSS-Klasse hinzugefügt , um im Formular hervorzuheben ):

Bildbeschreibung hier eingeben

Wenn Sie auch Änderungen an einem Rechnungsadressformular vornehmen möchten, verwenden Sie Custom \ Checkout \ Plugin \ AddressLayoutProcessor Klasse aktualisiert werden. Alles, was Sie tun müssen, ist, für eine bestimmte Zahlungsmethode dieselben Manipulationen mit der Rechnungsadresse durchzuführen wie für die Versandadressfelder.

Freue mich zu helfen!


Erstaunlich, danke! Ich hätte das nie geschafft, interessant wie es Backend Arbeit erfordert. Ich habe das von einem rein FE-Standpunkt aus angegangen. Wenn in ein paar Tagen niemand eine einfachere Lösung findet (wie ich glaube, einige andere Leute sehen sich das gerade an), werde ich es als akzeptiert markieren. Danke noch einmal.
Ben Crook

Ausgezeichnete Antwort :)
Keyur Shah

1

Dies ist kein empfohlener Weg, es ist einfach, aber nicht elegant:

app / code / Vendor / Module / view / frontend / layout / checkout_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
          <block class="Vendor\Salesman\Block\Checkout\Index" name="custom_checkout" before="-" template="Vendor_Module::checkout/index.phtml"/>
        </referenceContainer>
    </body>
</page>

app / code / Lime / Verkäufer / view / frontend / templates / checkout / index.phtml

<script>
  require([
      'jquery',
      'mage/mage'
  ], function($){
      $(document).ready(function () {
         //detect if the shipping form container loaded
         var existCondition = setInterval(function() {
            if ($('#shipping').length) {
              moveElement();
            }
         }, 100);

         function moveElement(){
             //get The field postcode and country
             var postcodeField = $("div[name='shippingAddress.postcode']");
             var countryField = $("div[name='shippingAddress.country_id']");
             // insert the wrapeer
             $( '<div class="wrapper"></div>' ).insertBefore( postcodeField);
             // move the fields to wrapper
             $(".wrapper").append(postcodeField);
             $(".wrapper").append(countryField);
         }
      });
    }
  });
</script>

Ich habe gestimmt, weil ich überzeugt bin, dass es funktionieren würde, aber ich stimme zu, dass es nicht sehr sauber ist. Ich würde es nicht verwenden, wenn es keine sauberere Methode gäbe. Vielen Dank.
Ben Crook
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.