Formulario de pago - Cómo envolver múltiples elementos en una clase - Magento 2

14

¿Cómo se envuelven dos elementos de formulario de pago dentro de un div?

Por ejemplo, digamos que quería envolver estos campos de país y código postal en un div con la clase de example-class, ¿cómo haría esto?

ingrese la descripción de la imagen aquí

Lo que he intentado

Traté de lograr esto agregándolos como hijos de <item name="shippingAddress" xsi:type="array">pero eso solo causa errores en la interfaz. Aunque recibí una entrada de texto en blanco sin una etiqueta dentro, .example-classhubo errores en la interfaz.

El error: Cannot read property 'indexedOptions' of undefined

Este es mi intento rápido:

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>

Tiene que haber una manera más fácil de hacer esto, o me falta algo o esta es la definición de ingeniería excesiva. Agregar un div sobre dos elementos nunca debería ser tan difícil.

Ben Crook
fuente

Respuestas:

17

Pregunta muy interesante Permítanme responder la última suposición sobre la implementación de Checkout. Es posible que se haya modificado un poco, ya que debe agregar más de 1 cambio en 1 archivo.

El enfoque no requiere realizar modificaciones en los módulos principales de Magento 2.

Para lograr su objetivo y envolver los campos de dirección de envío de pago en un elemento personalizado, se deben agregar los siguientes elementos:

  1. Archivo checkout_index_index.xml personalizado con la nueva definición de componente de IU
  2. Nueva plantilla HTML con elemento personalizado
  3. Complemento del procesador de diseño
  4. La declaración di.xml para el nuevo complemento

El archivo 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>

En el diseño, debemos agregar un nuevo componente de IU de grupo de campos personalizados . El componente tiene su propia plantilla Custom_Checkout \ view \ web \ template \ checkout \ field-group.html donde se representan todos los campos. Además, el componente de grupo de campos personalizados tiene el valor "0" para el nodo sortOrder . Permite representar el componente antes de todos los campos declarados como parte del componente de conjunto de campos de dirección de envío .

Además, hay un componente de UI de grupo de campos con su propia configuración de displayArea .

El archivo de plantilla Custom_Checkout \ view \ web \ template \ checkout \ field-group.html :

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

La plantilla permite representar todos los componentes agregados en la región del grupo de campos (también conocida como displayArea ).

El archivo de clase 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;
    }
}

La clase es responsable de copiar las configuraciones de los campos country_id y postcode en el componente de grupo de campos personalizados recién creado .

Los campos, una vez asignados al grupo de campos personalizados, deben marcarse como ocultos (visible = verdadero) para evitar la duplicación durante la representación. El componentDisabled no debe usarse para deshabilitar country_id y el código postal debido a otras dependencias (por ejemplo, archivo region.js) y al mecanismo de procesamiento de la dirección de envío.

El archivo 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>

El enfoque del complemento utilizado para los campos cambia porque los campos deben copiarse con una configuración completa. En caso de que Layout Processor declare en un módulo personalizado, el complemento detectará los cambios.

Como resultado, tanto los campos country_id como los códigos postales se representan en el formulario de dirección de envío y se envuelven en el elemento personalizado como se muestra a continuación (agregué algunos estilos para que la clase CSS personalizada se destaque en el formulario):

ingrese la descripción de la imagen aquí

Si también desea realizar modificaciones en un formulario de dirección de facturación, el Custom \ Checkout \ Plugin \ AddressLayoutProcessor debe actualizar la clase . Todo lo que tiene que hacer es realizar las mismas manipulaciones con la dirección de facturación para el método de pago específico que tenemos para los campos de dirección de envío.

¡Feliz de ayudar!

Max Pronko
fuente
Increíble, gracias! Nunca lo habría logrado, interesante cómo requiere trabajo de backend. Estaba abordando esto desde un punto de vista puramente FE. Si a nadie se le ocurre una solución más simple en unos días (como creo que otras personas están viendo esto actualmente), lo marcaré como aceptado. Gracias de nuevo.
Ben Crook
Excelente respuesta :)
Keyur Shah
Grandioso, muchas gracias. Esto funciona para mi.
Pratik Mehta
Si deseo el mismo cambio, ¿se aplica a la nueva dirección de facturación?
Pratik Mehta
1
Si también desea realizar modificaciones en un formulario de dirección de facturación, se debe actualizar la clase Custom \ Checkout \ Plugin \ AddressLayoutProcessor. Todo lo que tiene que hacer es realizar las mismas manipulaciones con la dirección de facturación para el método de pago específico que tenemos para los campos de dirección de envío.
Max Pronko
2

Esta no es una forma recomendada, es simple pero no elegante:

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
fuente
He votado porque estoy seguro de que funcionará, pero estoy de acuerdo en que no es muy limpio, no lo usaría a menos que no hubiera un método más limpio. Gracias.
Ben Crook