Magento 2: Como alterar o modelo de um bloco sem "nome"


10

Quero alterar para substituir o modelo de um bloco pelo meu modelo personalizado. Mas não tem um "nome", apenas um "como". O que eu quero substituir é:

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

Respostas:


8

Como substituir um modelo com layout ALIAS.

Esta resposta é um exemplo possível, você pode seguir isto para substituir o modelo do ALIAS.

Eu criei dois módulos de exemplo, Vendor_Moduletem layout com modelo de alias, estamos substituindo esse alias por Vendortwo_Moduletwomódulo.

Suponha que você saiba as etapas para criar o módulo, não estou postando a criação do módulo inteiro.

Módulo 1

\ app \ code \ Fornecedor \ Módulo \ 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>

Após remover o cache, executei http: // localhost / magento210 / module / test / test

O modelo de alias é substituído por Vendortwo_Moduletwo two/twoalias.phtml

insira a descrição da imagem aqui


Então, isso está substituindo um bloco por seu apelido? E se eu não quiser substituí-lo, mas adicionar outro bloco depois?
precisa saber é o seguinte

3

É assim que se faz corretamente e sem hacks.

Não procurei o caso de uso do OP, mas precisava modificar os renderizadores no carrinho. O problema é que, como no caso do OP, o Magento_Checkoutmódulo não fornece nomes para os renderizadores, o que significa que eles não podem ser referenciados e seus modelos alterados usando métodos tradicionais ou documentados. No entanto, após algumas investigações, descobri como fazê-lo usando as ferramentas que o Magento2 nos fornece diretamente no XML do layout.

Observe que existem outros lugares onde essa mesma abordagem funciona, como no Magento\Sales\Block\Items\AbstractItemsbloco. Os módulos Magento_Checkoute Magento_Salessão os dois que mais utilizam os representantes de itens, portanto, isso abrange muitas das consultas que levariam alguém a alterar o modelo de um bloco sem um nome. A razão pela qual isso foi publicado é devido à inevitabilidade de outras pessoas procurarem como modificar modelos de renderizador nos módulos de pagamento ou vendas.

Vou fornecer a solução primeiro e depois explicá-la em detalhes para quem quiser saber por que ela funciona.

Solução

Adicione o seguinte ao checkout_cart_index.xmlarquivo de layout:

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

Observe que o nome e o caminho do módulo precisam ser modificados para refletir sua base de código.

Explicação

Isso funciona aproveitando os overridden_templatesdados do bloco, que não são definidos por padrão.

Em Magento_Checkout, o checkout_cart_index.xmlarquivo de layout define o seguinte bloco:

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

Em seguida, define alguns desses renderizadores no checkout_cart_item_renderers.xmlarquivo de layout:

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

Infelizmente, eles não podem ser referenciados por seus aliases defaulte simple, respectivamente.

No entanto, olhando para o Magento\Checkout\Block\Cart\Gridbloco, que é nomeado checkout.cart.forme é o pai dos representantes, pode-se notar que há uma chamada para o getItemHtmlmétodo no modelo associado cart/form.phtml. Esse método então chama getItemRenderer. Ambos os métodos são definidos na Gridclasse pai de AbstractBlock. É aqui que os overridden_templatesdados são usados:

/**
 * 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);
}

Com esse conhecimento, o preenchimento do bloco com dados do XML de layout é simples, usando a argumentssintaxe do Magento2 .


11
Isso deve ser aceito como a verdadeira solução. Simples e eficaz. Maneira apropriada do Magento2. Ótima explicação. Obrigado!
Iva

2

Minha solução não é universal, é um "truque sujo", mas pode ser útil em certos casos. Minha amostra é para renderizador de front-end, não para adminhtml (acho que deve ser o mesmo).

Configure o ponto de interrupção \Magento\Framework\Data\Structure::getChildIdcom a condição " $ parentId == 'checkout.cart.item.renderers' " (este é um nome para o bloco pai, como você pode ver no checkout_cart_item_renderers.xmllayout). Todos os blocos filhos têm nomes próprios (computados):

insira a descrição da imagem aqui

Use estes nomes na atualização de layout do seu 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 quem olha para isso, esteja ciente de que isso vai cair se você apenas der um olhar distante. Não construa sua casa com cartões. Esses números não são garantidos.
Danemacmillan

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.