In Magento 1, as a module developer it's possible to change a block's template using layout XML code something like this

<reference name="block_to_change">
    <action method="setTemplate">
        <param>/path/to/template.phtml</param>
    </action>
</reference>

and then adding your template to the base theme.

app/design/frontend/base/default/template/path/to/template.phtml

Is it possible, as a module developer, to do something similar in Magento 2? Or would I need to use layout XML or PHP code to remove the block I'm interested in, and insert a new block with a different template (whose class extends the original block class's)

I know I could create a custom theme that replaces a template, but I'm interested in creating a module that changes the default template, but still allows a custom theme to then replace that template.

up vote 48 down vote accepted

Of course, it is possible:

<referenceBlock name="copyright">
    <action method="setTemplate">
        <argument name="template" xsi:type="string">Dfr_Backend::page/copyright.phtml</argument>
    </action>
</referenceBlock>
  • Can you explain the steps how can i change the layout, Actually i want to update the add to addtocart.phtml file according to system configuration and also want to update this using custom module – Deepak Mankotia Nov 25 '15 at 7:44
  • 5
    KAndy solution didn't work for me but this one yes – csmarvz Jan 26 '16 at 16:09
  • I have changed the template of the block name "customer_account_dashboard_top"<body> <referenceBlock name="customer_account_dashboard_top"> <action method="setTemplate"> <argument name="template" xsi:type="string">Namespace_Modulename::order/recentorder.phtml</argument> </action> </referenceBlock> </body>" but its not getting work, kindly check and let me know your comments – senthil Apr 26 at 17:36

Action node is deprecated, but you can use block arguments

<referenceBlock name="block_to_change">
    <arguments>
        <argument name="template" xsi:type="string">[Vendor]_[Module]::/path/to/template.phtml</argument>
    </arguments>
</referenceBlock>
  • Can you explain the steps how can i change the layout, Actually i want to update the add to addtocart.phtml file according to system configuration and also want to update this using custom module – Deepak Mankotia Nov 25 '15 at 7:44
  • 1
  • 4
    Thanks - I'll just leave a reference to a bug report here github.com/magento/magento2/issues/3356 - the method posted in this answer, while possibly the future way of doing things, does not yet work as advertised – Kristof at Fooman Mar 21 '16 at 10:27
  • 2
    @KAndy Is your code example 100% correct? I tried that and I can't get it to work in any way. The other answer from @Mage2.PRO (which uses <action method='setTemplate'>) works without problems. – maginfortis May 24 '16 at 8:52
  • 1
    This doesn't work. Accepted answer does though. – Milan Simek Aug 20 '17 at 22:20

To understand the difference between <arguments> and <action> you must understand how the constructors of Magento 2 objects work. If you override a constructor in Magento, you'll always get a $data-parameter which is an array. This is the data as provided in the XML files and translated to the internal $_data-array of \Magento\Framework\DataObject:

<referenceBlock name="catalog.topnav">
    <arguments>
        <argument name="template" xsi:type="string">Foo_Bar::buzz.phtml</argument>
    </arguments>
</referenceBlock>    

...

public function __construct(array $data = [])
{
    // $_data is populated with the arguments from XML:
    // so $_data['template'] is now 'Foo_Bar::buzz.phtml'
    $this->_data = $data;
}

However, in the case of a template, if setTemplate() is used in the pseudo constructor (_construct(), single underscore), this means that the $data is overridden, no matter if it's set in the XML.

public function _construct()
{
    $this->setTemplate('foo/bar.phtml');
}

In that scenario, <action> is prefered, since this is executed after the constructor & pseudo constructor.

<referenceBlock name="catalog.topnav">
    <action method="setTemplate">
        <argument name="template" xsi:type="string">Foo_Bar::buzz.phtml</argument>
    </action>
</referenceBlock> 

The following worked for me in Magento EE 2.2.3

<?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">
    <body>
        <referenceBlock name="core.module.block.name" template="[Vendor]_[Module]::path/to/your/template.phtml" />
    </body>
</page>

Note: if you are using a custom module to change core's template and you are going mad because the previous code snipped does not work, make sure your module is loaded after the core module you are trying to change (module.xml) and you executed bin/magento setup:upgrade :)

  • This is the cleanest way in my opinion. – Ben Crook May 25 at 16:02

I don't know why, but i find this way to be the best:

<referenceBlock name="sales.order.items.renderers.default" template="Foo_Bar::sales/order/items/renderer/default.phtml"/>
<referenceBlock name="sales.order.items.renderers.default" template="Foo_Bar::sales/order/items/renderer/default.phtml"/>

This will work only if your block wasn't overwritten before using setTemplate method. Magento 2.2.x and higher.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.