Formulir Checkout - Cara membungkus beberapa elemen dalam satu kelas - Magento 2

14

Bagaimana Anda membungkus dua elemen formulir checkout di dalam div?

Misalnya, saya ingin membungkus bidang negara dan kode pos / pos ini dalam div dengan kelas example-class, bagaimana saya melakukan ini?

masukkan deskripsi gambar di sini

Apa yang saya coba

Saya mencoba untuk mencapai ini dengan menambahkan mereka sebagai anak-anak <item name="shippingAddress" xsi:type="array">tetapi itu hanya menyebabkan kesalahan di frontend. Meskipun saya memang mendapatkan input teks kosong tanpa label di dalamnya .example-classada kesalahan di frontend.

Kesalahan: Cannot read property 'indexedOptions' of undefined

Ini adalah upaya cepat saya:

Magento_Checkout / web / template / alamat pengiriman / 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>

Harus ada cara yang lebih mudah untuk melakukan ini, baik saya kehilangan sesuatu atau ini adalah definisi over-engineering. Menambahkan div pada dua elemen seharusnya tidak sesulit ini.

Ben Crook
sumber

Jawaban:

17

Pertanyaan yang sangat menarik. Biarkan saya menjawab asumsi terakhir tentang implementasi Checkout. Mungkin sedikit over-engineered karena Anda harus menambahkan lebih dari 1 perubahan dalam 1 file.

Pendekatan ini tidak memerlukan modifikasi dalam modul inti Magento 2.

Untuk mencapai tujuan Anda dan membungkus bidang alamat pengiriman checkout ke elemen khusus, elemen berikut harus ditambahkan:

  1. File checkout_index_index.xml khusus dengan definisi Komponen UI yang baru
  2. Template HTML baru dengan elemen khusus
  3. Plugin Layout Processor
  4. Deklarasi di.xml untuk plugin baru

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

Dalam tata letak, kita harus menambahkan Komponen UI grup-bidang-kustom baru . Komponen memiliki templat sendiri Custom_Checkout \ view \ web \ template \ checkout \ field-group.html di mana semua bidang disajikan. Selain itu, komponen grup-bidang-kustom memiliki nilai "0" untuk simpul sortOrder . Hal ini memungkinkan rendering komponen sebelum semua bidang dinyatakan sebagai bagian dari komponen pengiriman-address-fieldset .

Juga, ada Komponen UI grup lapangan dengan pengaturan displayArea sendiri .

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

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

Templat memungkinkan rendering semua komponen ditambahkan ke wilayah grup lapangan (juga dikenal sebagai displayArea ).

File kelas 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;
    }
}

Kelas bertanggung jawab untuk menyalin konfigurasi bidang country_id dan kode pos ke komponen grup bidang bidang yang baru dibuat .

Bidang, setelah ditugaskan ke grup bidang-kustom harus ditandai sebagai disembunyikan (terlihat = benar) untuk menghindari duplikasi selama rendering. The componentDisabled tidak boleh digunakan untuk menonaktifkan country_id dan kode pos karena ketergantungan lainnya (misalnya region.js file) dan pengiriman mekanisme pengolahan alamat.

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

Pendekatan plugin yang digunakan untuk perubahan bidang karena bidang harus disalin dengan konfigurasi lengkap. Dalam hal Layout Processor dinyatakan dalam modul khusus, plugin akan menangkap perubahan.

Hasilnya, bidang country_id dan kode pos dirender dalam formulir alamat pengiriman dan dibungkus dengan elemen khusus seperti di bawah ini (saya menambahkan beberapa gaya untuk kelas CSS khusus agar terlihat menonjol dalam formulir):

masukkan deskripsi gambar di sini

Jika Anda juga ingin melakukan modifikasi pada formulir alamat penagihan, kelas Custom \ Checkout \ Plugin \ AddressLayoutProcessor harus diperbarui. Yang harus Anda lakukan adalah melakukan manipulasi yang sama dengan alamat penagihan untuk metode pembayaran tertentu seperti yang kami miliki untuk bidang alamat pengiriman.

Saya senang bisa membantu!

Max Pronko
sumber
Luar biasa, terima kasih! Saya tidak akan pernah berhasil itu, menarik bagaimana itu membutuhkan kerja backend. Saya menangani ini dari sudut pandang FE semata. Jika tidak ada yang menemukan solusi yang lebih sederhana dalam beberapa hari (seperti yang saya pikir beberapa orang sedang melihat ini) saya akan menandainya sebagai diterima. Terima kasih lagi.
Ben Crook
Jawaban yang sangat bagus :)
Keyur Shah
Luar biasa, terima kasih banyak. Ini bekerja untuk saya.
Pratik Mehta
Jika saya ingin perubahan yang sama berlaku untuk alamat penagihan yang baru?
Pratik Mehta
1
Jika Anda juga ingin melakukan modifikasi pada formulir alamat penagihan, kelas Custom \ Checkout \ Plugin \ AddressLayoutProcessor harus diperbarui. Yang harus Anda lakukan adalah melakukan manipulasi yang sama dengan alamat penagihan untuk metode pembayaran tertentu seperti yang kami miliki untuk bidang alamat pengiriman.
Max Pronko
2

Ini bukan cara yang disarankan, ini sederhana tetapi tidak elegan:

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
sumber
Saya telah memilih karena saya yakin itu akan berhasil tetapi saya setuju itu tidak sangat bersih, saya tidak akan menggunakan ini kecuali tidak ada metode yang lebih bersih. Terima kasih.
Ben Crook