チェックアウトフォーム-クラス内の複数の要素をラップする方法-Magento 2


14

div内で2つのチェックアウトフォーム要素をどのようにラップしますか?

たとえば、これらの国と郵便番号/郵便番号フィールドをのクラスでdivにラップしたいexample-class場合、どうすればよいでしょうか?

ここに画像の説明を入力してください

私が試したこと

私はそれらを子として追加することでこれを達成しようとしました<item name="shippingAddress" xsi:type="array">が、それはフロントエンドでエラーを引き起こすだけです。内部.example-classにラベルのない空白のテキスト入力を取得しましたが、フロントエンドにエラーがありました。

エラー: Cannot read property 'indexedOptions' of undefined

これは私の簡単な試みです:

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>

これを行うにはもっと簡単な方法が必要です。何かが欠けているか、これがオーバーエンジニアリングの定義です。2つの要素にdivを追加することは、決して難しいことではありません。

回答:


17

非常に興味深い質問です。Checkoutの実装に関する最後の仮定に答えさせてください。1つのファイルに1つ以上の変更を追加する必要があるため、少し過剰に設計されている場合があります。

このアプローチでは、Magento 2コアモジュールで変更を行う必要はありません。

目標を達成し、チェックアウト配送先住所フィールドをカスタム要素にラップするには、次の要素を追加する必要があります。

  1. 新しいUIコンポーネント定義を含むカスタムcheckout_index_index.xmlファイル
  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コンポーネントのsortOrderノードの値は「0」です。shipping-address-fieldsetの一部として宣言されたすべてのフィールドの前にコンポーネントをレンダリングできますコンポーネントのます。

また、独自のdisplayArea設定を持つフィールドグループ UIコンポーネントがあります。

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_idpostcodeフィールドの両方の構成を、新しく作成されたcustom-field-groupコンポーネントにコピーする役割を果たします。

custom-field-groupに割り当てられたフィールドは、レンダリング中の重複を避けるために非表示(visible = true)としてマークする必要があります。componentDisabledために、他の依存関係(例えばregion.jsファイル)および出荷アドレス処理機構にCOUNTRY_IDや郵便番号を無効にするために使用すべきではありません。

カスタム\チェックアウト\ ETC \フロントエンド\ 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フィールドとpostcodeフィールドの両方が配送先住所フォームにレンダリングされ、以下のようにカスタム要素にラップされます(フォームで際立つカスタム CSSクラスのスタイルをいくつか追加しました)。

ここに画像の説明を入力してください

請求先住所フォームに変更を加えたい場合は、Custom \ Checkout \ Plugin \ AddressLayoutProcessorクラスを更新する必要があります。あなたがしなければならないのは、配送先住所フィールドと同じように、特定の支払い方法の請求先住所で同じ操作を実行することです。

お力になれて、嬉しいです!


素晴らしい、ありがとう!私はそれをなんとかすることができなかったでしょう、興味深いことに、どのようにバックエンドの作業が必要になるのでしょうか。私は純粋にFEの観点からこれに取り組んでいました。数日以内に誰も簡単な解決策を思い付かない場合(他の人が現在これを見ていると思うので)、私はそれを受け入れられたものとしてマークします。再度、感謝します。
ベン・クルック

優秀な答え:)
キーアーシャー

素晴らしい、ありがとう。わたしにはできる。
プラティックメータ

同じ請求を新しい請求先住所に適用したい場合は?
プラティックメータ

1
請求先住所フォームの変更も行う場合は、Custom \ Checkout \ Plugin \ AddressLayoutProcessorクラスを更新する必要があります。あなたがしなければならないのは、配送先住所フィールドと同じように、特定の支払い方法の請求先住所で同じ操作を実行することです。
マックスプロンコ

2

これは推奨される方法ではありません。シンプルですがエレガントではありません。

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>

私はそれがうまくいくと確信しているので賛成しましたが、それはあまりきれいではないことに同意します。よりきれいな方法がなければこれを使用しません。ありがとう。
ベン・クルック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.