Magento 2: Jak zmienić szablon bloku bez „nazwy”

10

Chcę zmienić, aby zastąpić szablon bloku moim szablonem niestandardowym. Ale nie ma „nazwy”, ma tylko „as”. Ten, który chcę zastąpić, to:

<block class="Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\DefaultRenderer"
       as="default"
       template="order/view/items/renderer/default.phtml"/>
Ricky.C
źródło

Odpowiedzi:

8

Jak przesłonić szablon mający układ ALIAS.

Ta odpowiedź jest możliwym przykładem, możesz wykonać to, aby zastąpić szablon ALIAS.

Utworzyłem dwa przykładowe moduły, Vendor_Modulema układ z szablonem aliasu, zastępujemy ten alias według Vendortwo_Moduletwomodułu.

Załóżmy, że znasz kroki tworzenia modułu, nie publikuję tworzenia całego modułu.

Moduł 1

\ app \ code \ Vendor \ Module \ etc \ frontend \ route.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>

Moduł 2

\ app \ code \ Vendortwo \ Moduletwo \ etc \ frontend \ trasy.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>

Po usunięciu pamięci podręcznej uruchamiam http: // localhost / magento210 / module / test / test

Szablon aliasu jest zastępowany przez Vendortwo_Moduletwo two/twoalias.phtml

wprowadź opis zdjęcia tutaj

Krishna ijjada
źródło
Czy to zastępuje blok przez jego alias? Co jeśli nie chcę go zastąpić, ale dodać kolejny blok po nim?
Jānis Elmeris,
3

Oto jak to zrobić poprawnie i bez włamań.

Nie szukałem przypadku użycia OP, ale musiałem móc modyfikować rendery w koszyku. Problem polega na tym, że podobnie jak w przypadku OP Magento_Checkoutmoduł nie udostępnia nazw rendererom, co oznacza, że ​​nie można do nich odwoływać, a ich szablony zmieniać przy użyciu tradycyjnych lub udokumentowanych metod. Jednak po pewnym przemyśleniu odkryłem, jak to zrobić za pomocą narzędzi, które Magento2 zapewnia nam bezpośrednio w układzie XML.

Zauważ, że istnieją inne miejsca, w których działa to samo podejście, na przykład w Magento\Sales\Block\Items\AbstractItemsbloku. Magento_CheckoutI Magento_Salesmoduły są dwie, które wykorzystać maksimum renderujących element, więc ta obejmuje wiele zapytań, które mogłyby prowadzić kogoś do zmieniających się szablonowi bloku bez nazwy. Powodem tego jest fakt, że inni szukają sposobu modyfikowania szablonów renderera w modułach kas lub sprzedaży.

Najpierw przedstawię rozwiązanie, a następnie szczegółowo je wyjaśnię każdemu, kto chce wiedzieć, dlaczego to działa.

Rozwiązanie

Dodaj następujące elementy do checkout_cart_index.xmlpliku układu:

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

Zauważ, że nazwa modułu i ścieżka muszą zostać zmodyfikowane, aby odzwierciedlić bazę kodu.

Wyjaśnienie

Działa to poprzez wykorzystanie overridden_templatesdanych bloku, które nie są domyślnie zdefiniowane.

W Magento_CheckoutThe checkout_cart_index.xmlfile układ określa następujący blok:

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

Następnie definiuje kilka rendererów w checkout_cart_item_renderers.xmlpliku układu:

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

Niestety, nie można odwoływać się przez ich aliasów, defaulti simple, odpowiednio.

Jednak patrząc na Magento\Checkout\Block\Cart\Gridbloku, który jest nazwany checkout.cart.formi jest rodzicem renderujących, to można zauważyć, że nie jest to wywołanie getItemHtmlmetody w dołączonym szablonie cart/form.phtml. Ta metoda następnie wywołuje getItemRenderer. Obie te metody są zdefiniowane w Grid„s klasy dominującej AbstractBlock. Oto gdzie overridden_templateswykorzystywane są dane:

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

Dzięki tej wiedzy zapełnianie bloku danymi z układu XML jest proste przy użyciu argumentsskładni Magento2 .

danemacmillan
źródło
1
Należy to zaakceptować jako prawdziwe rozwiązanie. Prosty i skuteczny. Właściwy sposób Magento2. Świetne wyjaśnienie. Dziękuję Ci!
iva
2

Moje rozwiązanie nie jest uniwersalne, to „brudny hack”, ale w niektórych przypadkach może być przydatne. Moja próbka jest przeznaczona do renderowania interfejsu użytkownika, a nie do adminhtml (przypuszczam, że powinno być tak samo).

Ustaw punkt przerwania w \Magento\Framework\Data\Structure::getChildIdwarunku „ $ parentId == 'checkout.cart.item.renderers' ” (jest to nazwa bloku nadrzędnego, jak widać w checkout_cart_item_renderers.xmlukładzie). Wszystkie bloki potomne mają własne (obliczone) nazwy:

wprowadź opis zdjęcia tutaj

Użyj tych nazw w aktualizacji układu modułu:

    <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>
Alex Gusev
źródło
2
Każdemu, kto na to spojrzy, pamiętaj, że to się przewróci, jeśli tylko spojrzysz na niego z dystansem. Nie buduj domu za pomocą kart. Te liczby nie są gwarantowane.
danemacmillan
0

Proszę zobaczyć moją odpowiedź tutaj: https://magento.stackexchange.com/a/239387/14403

Wierzę, że to rozwiązanie będzie dla ciebie najlepsze. Rozwiązanie obejmuje zastąpienie dowolnego bloku / szablonu, który nie ma aliasu tylko z nazwą.

Kod RLT
źródło