แบบฟอร์มการชำระเงิน - วิธีการห่อองค์ประกอบหลายรายการในชั้นเรียน - วีโอไอพี 2


14

คุณจะห่อองค์ประกอบของฟอร์มการชำระเงินสองส่วนไว้ใน div ได้อย่างไร

ตัวอย่างเช่นสมมติว่าฉันต้องการห่อเขตข้อมูลประเทศและไปรษณีย์ / รหัสไปรษณีย์ใน div ด้วยคลาสของexample-classฉันจะทำสิ่งนี้ได้อย่างไร

ป้อนคำอธิบายรูปภาพที่นี่

สิ่งที่ฉันได้ลอง

ฉันพยายามที่จะบรรลุสิ่งนี้โดยการเพิ่มพวกเขาเป็นลูก ๆ ของ<item name="shippingAddress" xsi:type="array">แต่นั่นก็ทำให้เกิดข้อผิดพลาดในส่วนหน้า แม้ว่าฉันจะได้รับการป้อนข้อความเปล่าโดยไม่มีป้ายกำกับภายใน.example-classมีข้อผิดพลาดในส่วนหน้า

ข้อผิดพลาด: Cannot read property 'indexedOptions' of undefined

นี่คือความพยายามอย่างรวดเร็วของฉัน:

Magento_Checkout / เว็บ / แม่แบบ / การจัดส่งสินค้าที่อยู่ / 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>

จะต้องมีวิธีที่ง่ายกว่าในการทำสิ่งนี้ไม่ว่าฉันจะทำบางสิ่งบางอย่างขาดหายไปหรือนี่คือคำจำกัดความของวิศวกรรมที่มากเกินไป การเพิ่มตัวหารสององค์ประกอบไม่น่าจะเป็นเรื่องยาก

คำตอบ:


17

คำถามที่น่าสนใจมาก ฉันขอตอบข้อสมมติสุดท้ายเกี่ยวกับการใช้งาน Checkout มันอาจจะเกินความเป็นวิศวกรเพราะคุณต้องเพิ่มการเปลี่ยนแปลงมากกว่า 1 ไฟล์ใน 1 ไฟล์

วิธีนี้ไม่จำเป็นต้องทำการปรับเปลี่ยนในโมดูลหลักของ Magento 2

เพื่อให้บรรลุเป้าหมายของคุณและห่อเขตข้อมูลที่อยู่จัดส่งในองค์ประกอบที่กำหนดเองควรเพิ่มองค์ประกอบต่อไปนี้:

  1. ไฟล์ checkout_index_index.xml แบบกำหนดเองพร้อมนิยาม UI Component ใหม่
  2. เทมเพลต HTML ใหม่พร้อมองค์ประกอบที่กำหนดเอง
  3. ปลั๊กอินตัวประมวลผลเค้าโครง
  4. การประกาศ di.xml สำหรับปลั๊กอินใหม่

Custom_Checkout \ มุมมอง \ ส่วนหน้า \ รูปแบบ \ 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>

ในเลย์เอาต์เราควรเพิ่มส่วนประกอบ UI แบบกำหนดเอง - ฟิลด์ - กลุ่มใหม่ คอมโพเนนต์มีเทมเพลตของตัวเองCustom_Checkout \ view \ web \ template \ checkout \ field-group.htmlที่มีการแสดงผลฟิลด์ทั้งหมด นอกจากนี้องค์ประกอบcustom-field-groupมีค่า "0" สำหรับโหนดsortOrder อนุญาตให้เรนเดอร์ส่วนประกอบก่อนที่จะประกาศฟิลด์ทั้งหมดเป็นส่วนหนึ่งของส่วนประกอบที่อยู่การจัดส่ง - fieldset

นอกจากนี้ยังมีองค์ประกอบ UI กลุ่มฟิลด์ที่มีการตั้งค่าdisplayAreaของตัวเอง

Custom_Checkout \ มุมมอง \ เว็บ \ แม่แบบ \ เช็คเอาท์ \ สนาม group.htmlแฟ้มแม่แบบ:

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

เทมเพลตช่วยให้การเรนเดอร์ส่วนประกอบทั้งหมดที่เพิ่มลงในขอบเขตกลุ่มฟิลด์ (หรือที่เรียกว่าdisplayArea )

กำหนดเอง \ ร้า \ ปลั๊กอิน \ 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;
    }
}

ชั้นเป็นผู้รับผิดชอบสำหรับการคัดลอกทั้งcountry_idและรหัสไปรษณีย์เขตกำหนดค่าลงในที่สร้างขึ้นใหม่ที่กำหนดเองฟิลด์กลุ่มส่วนประกอบ

ฟิลด์เมื่อกำหนดให้กับcustom-field-groupควรถูกทำเครื่องหมายว่าซ่อนอยู่ (visible = true) เพื่อหลีกเลี่ยงการทำซ้ำระหว่างการเรนเดอร์ componentDisabledไม่ควรนำมาใช้สำหรับการปิดใช้งานและรหัสไปรษณีย์ country_id เนื่องจากการอ้างอิงอื่น ๆ (เช่น region.js ไฟล์) และการจัดส่งสินค้ากลไกการประมวลผลอยู่

ไฟล์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>

วิธีการปลั๊กอินที่ใช้สำหรับฟิลด์เปลี่ยนแปลงเนื่องจากควรคัดลอกฟิลด์ด้วยการกำหนดค่าที่สมบูรณ์ ในกรณีที่ตัวประมวลผลเค้าโครงประกาศในโมดูลที่กำหนดเองปลั๊กอินจะตรวจจับการเปลี่ยนแปลง

เป็นผลให้ทั้งcountry_idและเขตข้อมูลรหัสไปรษณีย์จะแสดงผลในรูปแบบที่อยู่จัดส่งและห่อลงในองค์ประกอบที่กำหนดเองตามด้านล่าง (ฉันได้เพิ่มรูปแบบเล็กน้อยสำหรับคลาส CSS ที่กำหนดเองเพื่อให้โดดเด่นในแบบฟอร์ม):

ป้อนคำอธิบายรูปภาพที่นี่

หากคุณต้องการแก้ไขแบบฟอร์มที่อยู่สำหรับการเรียกเก็บเงินคลาสCustom \ Checkout \ Plugin \ AddressLayoutProcessorควรได้รับการอัปเดต สิ่งที่คุณต้องทำคือดำเนินการจัดการกับที่อยู่สำหรับการเรียกเก็บเงินสำหรับวิธีการชำระเงินที่เฉพาะเจาะจงเช่นเดียวกับที่เรามีสำหรับฟิลด์ที่อยู่สำหรับจัดส่ง

ยินดีที่ได้ช่วย!


น่าทึ่งขอบคุณ! ฉันจะไม่เคยมีการจัดการที่น่าสนใจว่ามันต้องทำงานแบ็กเอนด์ ฉันกำลังแก้ไขปัญหานี้จากมุมมองของ FE ล้วนๆ หากไม่มีใครคิดวิธีที่ง่ายกว่านี้ในอีกสองสามวัน (เพราะฉันคิดว่าบางคนกำลังมองดูสิ่งนี้อยู่) ฉันจะทำเครื่องหมายว่าเป็นที่ยอมรับ ขอบคุณอีกครั้ง.
Ben Crook

คำตอบที่ยอดเยี่ยม :)
Keyur Shah

เยี่ยมมากขอบคุณมาก มันใช้งานได้สำหรับฉัน
Pratik Mehta

หากฉันต้องการการเปลี่ยนแปลงเดียวกันนี้จะใช้กับที่อยู่สำหรับการเรียกเก็บเงินใหม่ได้หรือไม่
Pratik Mehta

1
หากคุณต้องการแก้ไขแบบฟอร์มการเรียกเก็บเงินคลาส Custom \ Checkout \ Plugin \ AddressLayoutProcessor ควรได้รับการอัปเดต สิ่งที่คุณต้องทำคือดำเนินการจัดการกับที่อยู่การเรียกเก็บเงินสำหรับวิธีการชำระเงินที่เฉพาะเจาะจงเช่นเดียวกับที่เรามีสำหรับฟิลด์ที่อยู่สำหรับจัดส่ง
Max Pronko

2

นี่ไม่ใช่วิธีที่แนะนำมันง่าย แต่ไม่หรูหรา:

app / รหัส / ผู้ขาย / โมดูล / view / ส่วนหน้า / รูปแบบ / 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 / รหัส / มะนาว / พนักงานขาย / ดู / ส่วนหน้า / แม่ / ชำระเงิน / 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>

ฉัน upvoted เนื่องจากฉันมั่นใจว่าจะใช้งานได้ แต่ฉันยอมรับว่ามันไม่สะอาดมากฉันจะไม่ใช้สิ่งนี้เว้นแต่ว่าจะไม่มีวิธีที่สะอาดกว่า ขอบคุณ
Ben Crook
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.