Kasa - Jak owinąć wiele elementów w klasie - Magento 2

14

Jak owinąć dwa elementy formularza kasy w div?

Na przykład powiedzmy, że chciałem owinąć pola kraju i kodu pocztowego w div z klasą example-class, jak mam to zrobić?

wprowadź opis zdjęcia tutaj

Co próbowałem

Próbowałem to osiągnąć, dodając je jako dzieci, <item name="shippingAddress" xsi:type="array">ale to tylko powoduje błędy w interfejsie użytkownika. Chociaż dostałem puste wprowadzanie tekstu bez etykiety wewnątrz .example-class, były błędy na interfejsie.

Błąd: Cannot read property 'indexedOptions' of undefined

To moja szybka próba:

Magento_Checkout / web / template / shipping-address / 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>

Musi być łatwiejszy sposób na zrobienie tego, albo coś mi brakuje, albo taka jest definicja nadmiernej inżynierii. Dodanie div dla dwóch elementów nigdy nie powinno być tak trudne.

Ben Crook
źródło

Odpowiedzi:

17

Bardzo interesujące pytanie. Pozwól mi odpowiedzieć na ostatnie założenie dotyczące realizacji usługi Checkout. Może być nieco przerobiony, ponieważ musisz dodać więcej niż tylko 1 zmianę w 1 pliku.

Podejście to nie wymaga wykonywania modyfikacji w modułach podstawowych Magento 2.

Aby osiągnąć cel i zawrzeć pola adresu wysyłki kasy w niestandardowym elemencie, należy dodać następujące elementy:

  1. Niestandardowy plik checkout_index_index.xml z nową definicją składnika interfejsu użytkownika
  2. Nowy szablon HTML z niestandardowym elementem
  3. Wtyczka procesora układu
  4. Deklaracja di.xml dla nowej wtyczki

Plik 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>

W układzie powinniśmy dodać nowy komponent interfejsu użytkownika grupy pól niestandardowych . Składnik ma własny szablon Custom_Checkout \ view \ web \ template \ checkout \ field-group.html, w którym są renderowane wszystkie pola. Ponadto komponent custom-field-group ma wartość „0” dla węzła sortOrder . Umożliwia renderowanie komponentu przed wszystkimi polami zadeklarowanymi jako część komponentu zestawu adresów wysyłkowych .

Ponadto istnieje komponent interfejsu użytkownika grupy pól z własnym ustawieniem displayArea .

Plik szablonu Custom_ Checkout \ view \ web \ template \ checkout \ field-group.html :

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

Szablon umożliwia renderowanie wszystkich komponentów dodanych do regionu grupy pól (znanego również jako displayArea ).

Plik klasy 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;
    }
}

Klasa odpowiada za kopiowanie konfiguracji pól country_id i kodów pocztowych do nowo utworzonego komponentu custom-field-group .

Pola raz przypisane do grupy pól niestandardowych należy oznaczyć jako ukryte (widoczne = prawda), aby uniknąć powielania podczas renderowania. Składnika componentDisabled nie należy używać do wyłączania country_id i kodu pocztowego z powodu innych zależności (np. Plik region.js) i mechanizmu przetwarzania adresu wysyłki.

Plik 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>

Podejście wtyczki zastosowane do pól zmienia się, ponieważ pola należy skopiować z pełną konfiguracją. W przypadku zadeklarowania przez procesor układu w module niestandardowym wtyczka przechwytuje zmiany.

W rezultacie zarówno pola country_id , jak i pola kodu pocztowego są renderowane w formularzu adresu wysyłki i zawijane do elementu niestandardowego, tak jak poniżej (dodałem kilka stylów, aby niestandardowa klasa CSS wyróżniała się w formularzu):

wprowadź opis zdjęcia tutaj

Jeśli chcesz również zmodyfikować formularz adresu rozliczeniowego, klasa Custom \ Checkout \ Plugin \ AddressLayoutProcessor powinna zostać zaktualizowana. Wszystko, co musisz zrobić, to wykonać takie same operacje przy użyciu adresu rozliczeniowego dla określonej metody płatności, jak w przypadku pól adresu wysyłki.

Chętnie pomoże!

Max Pronko
źródło
Niesamowite, dziękuję! Nigdy bym tego nie zrobił, ciekawe, jak wymaga to pracy zaplecza. Zajmowałem się tym z czysto FE. Jeśli nikt nie wymyśli prostszego rozwiązania w ciągu kilku dni (jak sądzę, niektórzy inni obecnie na to patrzą) oznaczę to jako zaakceptowane. Dzięki jeszcze raz.
Ben Crook,
Doskonała odpowiedź :)
Keyur Shah,
Wspaniale, dziękuję bardzo. Mi to pasuje.
Pratik Mehta
Jeśli chcę, aby ta sama zmiana dotyczyła nowego adresu rozliczeniowego?
Pratik Mehta
1
Jeśli chcesz również zmodyfikować formularz adresu rozliczeniowego, klasa Custom \ Checkout \ Plugin \ AddressLayoutProcessor powinna zostać zaktualizowana. Wszystko, co musisz zrobić, to wykonać takie same operacje przy użyciu adresu rozliczeniowego dla konkretnej metody płatności, jak w przypadku pól adresu wysyłki.
Max Pronko
2

To nie jest zalecany sposób, jest prosty, ale nie elegancki:

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 / Salesman / 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>
Shell Suite
źródło
Głosowałem, bo jestem pewien, że to zadziała, ale zgadzam się, że nie jest bardzo czysty, nie użyłbym tego, chyba że nie byłoby czystszej metody. Dzięki.
Ben Crook,