Formulaire de commande - Comment encapsuler plusieurs éléments dans une classe - Magento 2


14

Comment encapsuler deux éléments de formulaire de paiement dans un div?

Par exemple, disons que je voulais encapsuler ces champs de pays et de code postal / zip dans une div avec la classe de example-class, comment dois-je procéder?

entrez la description de l'image ici

Ce que j'ai essayé

J'ai essayé d'y parvenir en les ajoutant en tant qu'enfants de <item name="shippingAddress" xsi:type="array">mais cela ne fait que provoquer des erreurs sur le frontend. Bien que j'aie obtenu une entrée de texte vierge sans étiquette à l'intérieur, .example-classil y avait des erreurs sur le frontend.

L'erreur: Cannot read property 'indexedOptions' of undefined

Ceci est ma tentative rapide:

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>

Il doit y avoir un moyen plus simple de le faire, soit il me manque quelque chose, soit c'est la définition de la suringénierie. L'ajout d'un div sur deux éléments ne devrait jamais être aussi difficile.

Réponses:


17

Question très intéressante. Permettez-moi de répondre à la dernière hypothèse concernant la mise en œuvre de Checkout. Il pourrait être un peu trop complexe car vous devez ajouter plus d'une seule modification dans un fichier.

L'approche ne nécessite pas d'effectuer des modifications dans les modules de base de Magento 2.

Afin d'atteindre votre objectif et d'envelopper les champs d'adresse de livraison de la commande dans un élément personnalisé, les éléments suivants doivent être ajoutés:

  1. Fichier checkout_index_index.xml personnalisé avec la nouvelle définition de composant d'interface utilisateur
  2. Nouveau modèle HTML avec élément personnalisé
  3. Plugin du processeur de mise en page
  4. La déclaration di.xml pour le nouveau plugin

Le fichier 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>

Dans la mise en page, nous devons ajouter un nouveau composant d'interface utilisateur de groupe de champs personnalisés . Le composant a son propre modèle Custom_Checkout \ view \ web \ template \ checkout \ field-group.html où tous les champs sont rendus. En outre, le composant de groupe de champs personnalisés a la valeur "0" pour le nœud sortOrder . Il permet de rendre le composant avant tous les champs déclarés comme faisant partie du composant shipping-address-fieldset .

En outre, il existe un composant d'interface utilisateur de groupe de champs avec son propre paramètre displayArea .

Le Custom_Checkout de point de vue \ web \ template \ checkout \ field-group.html fichier modèle:

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

Le modèle permet de rendre tous les composants ajoutés dans la région du groupe de champs (également appelé displayArea ).

La commande \ Commander \ Plugin \ AddressLayoutProcessor fichier de classe:

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

La classe est chargée de copier les configurations des champs country_id et postcode dans le composant de groupe de champs personnalisé nouvellement créé .

Les champs, une fois attribués au groupe de champs personnalisés, doivent être marqués comme masqués (visible = vrai) afin d'éviter la duplication lors du rendu. Le componentDisabled ne doit pas être utilisé pour désactiver country_id et code postal en raison d'autres dépendances (par exemple, fichier region.js) et du mécanisme de traitement des adresses d'expédition.

Le fichier 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>

L'approche du plugin utilisée pour les champs change car les champs doivent être copiés avec une configuration complète. Dans le cas où le Layout Processor est déclaré dans un module personnalisé, le plugin interceptera les modifications.

En conséquence, les champs country_id et postcode sont affichés dans le formulaire d'adresse de livraison et enveloppés dans l'élément personnalisé comme ci-dessous (j'ai ajouté quelques styles pour que la classe CSS personnalisée se démarque dans le formulaire):

entrez la description de l'image ici

Si vous souhaitez également apporter des modifications à un formulaire d'adresse de facturation, la classe Custom \ Checkout \ Plugin \ AddressLayoutProcessor doit être mise à jour. Tout ce que vous avez à faire est d'effectuer les mêmes manipulations avec l'adresse de facturation pour le mode de paiement spécifique que pour les champs d'adresse de livraison.

Heureux d'aider!


Incroyable, merci! Je n'aurais jamais réussi cela, intéressant de voir comment cela nécessite un travail de backend. J'abordais cela d'un point de vue purement FE. Si personne ne propose une solution plus simple dans quelques jours (comme je pense que d'autres personnes sont en train de regarder cela), je la marquerai comme acceptée. Merci encore.
Ben Crook

Excellente réponse :)
Keyur Shah

Génial, merci beaucoup. Ça marche pour moi.
Pratik Mehta

Si je veux que le même changement s'applique à la nouvelle adresse de facturation, alors?
Pratik Mehta

1
Si vous souhaitez également apporter des modifications à un formulaire d'adresse de facturation, la classe Custom \ Checkout \ Plugin \ AddressLayoutProcessor doit être mise à jour. Tout ce que vous avez à faire est d'effectuer les mêmes manipulations avec l'adresse de facturation pour le mode de paiement spécifique que nous avons pour les champs d'adresse de livraison.
Max Pronko

2

Ce n'est pas une méthode recommandée, c'est simple mais pas élégant:

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>

J'ai voté positivement car je suis convaincu que cela fonctionnerait, mais je suis d'accord qu'il n'est pas très propre, je ne l'utiliserais pas s'il n'y avait pas de méthode plus propre. Merci.
Ben Crook
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.