Magento 2: come cambiare il modello di un blocco senza "nome"


10

Voglio cambiare per sovrascrivere il modello di un blocco con il mio modello personalizzato. Ma non ha un "nome", ha solo un "as". Quello che voglio sovrascrivere è:

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

Risposte:


8

Come sovrascrivere un modello con layout ALIAS.

Questa risposta è un possibile esempio, puoi seguirla per sovrascrivere il modello ALIAS.

Ho creato due moduli di esempio, Vendor_Moduleha un layout con modello di alias, Stiamo sostituendo questo alias per Vendortwo_Moduletwomodulo.

Supponiamo di conoscere i passaggi per creare il modulo, non sto pubblicando la creazione dell'intero modulo.

Modulo 1

\ App \ code \ Venditore \ 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 \ vista Venditore \ Module \ \ 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>

Modulo 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 \ vista \ 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>

Dopo aver rimosso la cache, eseguo http: // localhost / magento210 / module / test / test

Il modello alias viene sostituito da Vendortwo_Moduletwo two/twoalias.phtml

inserisci qui la descrizione dell'immagine


Quindi, questo ha la precedenza su un blocco dal suo alias? E se non volessi sovrascriverlo ma aggiungere un altro blocco dopo di esso?
Jānis Elmeris,

3

Ecco come farlo correttamente e senza hack.

Non ho cercato il caso d'uso di OP, ma dovevo essere in grado di modificare i renderer nel carrello. Il problema è che, come nel caso di OP, il Magento_Checkoutmodulo non fornisce nomi ai renderer, il che significa che non possono essere referenziati e che i loro modelli possono essere cambiati usando metodi tradizionali o documentati. Tuttavia, dopo un po 'di investigazione, ho scoperto come farlo utilizzando gli strumenti che Magento2 ci fornisce direttamente nel layout XML.

Nota che ci sono altri posti in cui funziona lo stesso approccio, come nel Magento\Sales\Block\Items\AbstractItemsblocco. I moduli Magento_Checkoute Magento_Salessono i due che utilizzano maggiormente i renderer di elementi, quindi questo copre molte delle query che porterebbero qualcuno a cambiare il modello di un blocco senza un nome. Il motivo per cui questo è stato pubblicato è a causa dell'inevitabilità di altri che cercano come modificare i modelli di rendering nei moduli di pagamento o di vendita.

Prima fornirò la soluzione e poi la spiegherò in dettaglio a chiunque voglia sapere perché funziona.

Soluzione

Aggiungi quanto segue al checkout_cart_index.xmlfile di 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>

Nota che il nome e il percorso del modulo devono essere modificati per riflettere la tua base di codice.

Spiegazione

Funziona sfruttando i overridden_templatesdati del blocco, che non è definito per impostazione predefinita.

In Magento_Checkout, il checkout_cart_index.xmlfile di layout definisce il seguente blocco:

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

Definisce quindi un paio di quei renderer nel checkout_cart_item_renderers.xmlfile di 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>

Sfortunatamente, non possono essere referenziati dai loro alias defaulte simple, rispettivamente.

Tuttavia, esaminando la Magento\Checkout\Block\Cart\GridBlock, che prende il nome checkout.cart.form, ed è la madre delle renderer, si può notare che c'è una chiamata al getItemHtmlmetodo nel modello associato, cart/form.phtml. Quel metodo chiama quindi getItemRenderer. Entrambi questi metodi sono definiti nella Gridclasse genitore 's, AbstractBlock. Qui è dove overridden_templatesvengono utilizzati i dati:

/**
 * 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 questa conoscenza, la compilazione del blocco con i dati dal layout XML è semplice usando la argumentssintassi di Magento2 .


1
Questo dovrebbe essere accettato come la vera soluzione. Semplice ed efficace Modo Magento2 corretto. Ottima spiegazione Grazie!
iva,

2

La mia soluzione non è universale, è un "trucco sporco" ma può essere utile in alcuni casi. Il mio esempio è per il renderer frontend, non per adminhtml (suppongo che dovrebbe essere lo stesso).

Punto di interruzione dell'installazione\Magento\Framework\Data\Structure::getChildId con la condizione " $ parentId == 'checkout.cart.item.renderers' " (questo è un nome per il blocco padre come puoi vedere nel checkout_cart_item_renderers.xmllayout). Tutti i blocchi figlio hanno nomi propri (calcolati):

inserisci qui la descrizione dell'immagine

Usa questi nomi nell'aggiornamento del layout del tuo modulo:

    <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
A chiunque lo guardi, tieni presente che questo cadrà se lo guardi anche solo in disparte. Non costruire la tua casa con le carte. Quei numeri non sono garantiti.
Danemacmillan,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.