Magento 2: Cómo cambiar la plantilla de un bloque sin "nombre"


10

Quiero cambiar para anular la plantilla de un bloque con mi plantilla personalizada. Pero no tiene un "nombre", solo tiene un "como". El que quiero anular es:

<block class="Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\DefaultRenderer"
       as="default"
       template="order/view/items/renderer/default.phtml"/>

Respuestas:


8

Cómo anular una plantilla con diseño ALIAS.

Esta respuesta es un posible ejemplo, puede seguir esto para anular la plantilla de ALIAS.

He creado dos módulos de ejemplo, Vendor_Moduletiene un diseño con plantilla de alias, estamos anulando este alias por Vendortwo_Moduletwomódulo.

Suponga que conoce los pasos para crear el módulo, no estoy publicando la creación completa del módulo.

Módulo 1

\ app \ code \ Vendor \ Module \ etc \ frontend \ routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="module" frontName="module">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>

\ app \ code \ Vendor \ Module \ view \ frontend \ layout \ module_test_test.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
     <body>     
        <referenceContainer name="content">         
            <block class="Vendor\Module\Block\Test\Test" name="test_test" template="test/test.phtml">
                <block class="Vendor\Module\Block\Test\Test" as="testali" template="test/testali.phtml"/>
            </block>
        </referenceContainer>      
    </body>
</page>

Módulo 2

\ app \ code \ Vendortwo \ Moduletwo \ etc \ frontend \ routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="moduletwo" frontName="moduletwo">
            <module name="Vendortwo_Moduletwo" />
        </route>
    </router>
</config>

\ app \ code \ Vendortwo \ Moduletwo \ view \ frontend \ layout \ default.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <referenceBlock name="test_test">
            <block class="Vendortwo\Moduletwo\Block\Two\Two" as="testali" template="two/twoalias.phtml"/>
        </referenceBlock>
</page>

Después de eliminar el caché, ejecuto http: // localhost / magento210 / module / test / test

La plantilla de alias es anulada por Vendortwo_Moduletwo two/twoalias.phtml

ingrese la descripción de la imagen aquí


Entonces, ¿esto está anulando un bloque por su alias? ¿Qué sucede si no quiero anularlo pero agregar otro bloque después?
Jānis Elmeris

3

Así es como hacerlo correctamente y sin hacks.

No busqué el caso de uso de OP, pero necesitaba poder modificar los renderizadores dentro del carrito. El problema es que, como en el caso de OP, el Magento_Checkoutmódulo no proporciona nombres a los renderizadores, lo que significa que no se puede hacer referencia a ellos y que sus plantillas se cambian utilizando métodos tradicionales o documentados. Sin embargo, después de investigar un poco, descubrí cómo hacerlo utilizando las herramientas que Magento2 nos proporciona directamente en el diseño XML.

Tenga en cuenta que hay otros lugares donde funciona este mismo enfoque, como en el Magento\Sales\Block\Items\AbstractItemsbloque. Los módulos Magento_Checkouty Magento_Salesson los dos que más utilizan los renderizadores de elementos, por lo que cubre muchas de las consultas que llevarían a alguien a cambiar la plantilla de un bloque sin un nombre. La razón por la que esto se publicó se debe a la inevitabilidad de que otros busquen cómo modificar las plantillas de renderizador en los módulos de pago o ventas.

Primero voy a proporcionar la solución, y luego la explicaré en detalle para cualquiera que quiera saber por qué funciona.

Solución

Agregue lo siguiente al checkout_cart_index.xmlarchivo de diseño:

<referenceBlock name="checkout.cart.form">
    <arguments>
        <argument name="overridden_templates" xsi:type="array">
            <item name="default" xsi:type="string">LinusShops_Moneymaker::Magento_Checkout/cart/item/default.phtml</item>
            <item name="simple" xsi:type="string">LinusShops_Moneymaker::Magento_Checkout/cart/item/simple.phtml</item>
            <item name="configurable" xsi:type="string">LinusShops_Moneymaker::Magento_Checkout/cart/item/configurable.phtml</item>
        </argument>
    </arguments>
</referenceBlock>

Tenga en cuenta que el nombre y la ruta del módulo deben modificarse para reflejar su base de código.

Explicación

Esto funciona aprovechando los overridden_templatesdatos del bloque, que no está definido por defecto.

En Magento_Checkout, el checkout_cart_index.xmlarchivo de diseño define el siguiente bloque:

<block class="Magento\Checkout\Block\Cart\Grid" name="checkout.cart.form" as="cart-items" template="cart/form.phtml" after="cart.summary">
    <block class="Magento\Framework\View\Element\RendererList" name="checkout.cart.item.renderers" as="renderer.list"/>
    <block class="Magento\Framework\View\Element\Text\ListText" name="checkout.cart.order.actions"/>
</block>

Luego define un par de esos renderizadores en el checkout_cart_item_renderers.xmlarchivo de diseño:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="checkout_item_price_renderers"/>
    <body>
        <referenceBlock name="checkout.cart.item.renderers">
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="default" template="cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.default.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.default.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.default.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="simple" template="cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.simple.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.simple.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.simple.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
        </referenceBlock>
    </body>
</page>

Desafortunadamente, no pueden ser referenciados por sus alias defaulty simple, respectivamente.

Sin embargo, al observar el Magento\Checkout\Block\Cart\GridBloque, que se llama checkout.cart.formy es el padre de los renderizadores, se puede observar que hay una llamada al getItemHtmlmétodo en la plantilla asociada cart/form.phtml. Ese método luego llama getItemRenderer. Ambos métodos se definen en Gridla clase padre de AbstractBlock. Aquí es donde overridden_templatesse usan los datos:

/**
 * Retrieve item renderer block
 *
 * @param string|null $type
 * @return \Magento\Framework\View\Element\Template
 * @throws \RuntimeException
 */
public function getItemRenderer($type = null)
{
    if ($type === null) {
        $type = self::DEFAULT_TYPE;
    }
    $rendererList = $this->_getRendererList();
    if (!$rendererList) {
        throw new \RuntimeException('Renderer list for block "' . $this->getNameInLayout() . '" is not defined');
    }
    $overriddenTemplates = $this->getOverriddenTemplates() ?: [];
    $template = isset($overriddenTemplates[$type]) ? $overriddenTemplates[$type] : $this->getRendererTemplate();
    return $rendererList->getRenderer($type, self::DEFAULT_TYPE, $template);
}

Con este conocimiento, llenar el bloque con datos del diseño XML es sencillo utilizando la argumentssintaxis de Magento2 .


1
Esto debe ser aceptado como la verdadera solución. Simple y efectivo. Forma correcta de Magento2. Gran explicación ¡Gracias!
iva

2

Mi solución no es universal, es un "truco sucio" pero puede ser útil en ciertos casos. Mi muestra es para el renderizador frontend, no para adminhtml (supongo que debería ser lo mismo).

Configure el punto de interrupción \Magento\Framework\Data\Structure::getChildIdcon la condición " $ parentId == 'checkout.cart.item.renderers' " (este es un nombre para el bloque primario como puede ver en el checkout_cart_item_renderers.xmldiseño). Todos los bloques secundarios tienen nombres propios (calculados):

ingrese la descripción de la imagen aquí

Use estos nombres en la actualización de diseño de su módulo:

    <referenceBlock name="checkout.cart.item.renderers_schedule_block4">
        <action method="setTemplate">
            <argument name="template" xsi:type="string">Vendor_Module::cart/item/default.phtml</argument>
        </action>
    </referenceBlock>

2
Para cualquiera que esté mirando esto, tenga en cuenta que esto se caerá si incluso le da una mirada distante. No construyas tu casa con cartas. Esos números no están garantizados.
danemacmillan

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.