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.
6 Answers 6
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 moduleDeepak Mankotia– Deepak Mankotia2015年11月25日 07:44:32 +00:00Commented Nov 25, 2015 at 7:44
-
5KAndy solution didn't work for me but this one yescsmarvz– csmarvz2016年01月26日 16:09:36 +00:00Commented Jan 26, 2016 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 commentssenthil– senthil2018年04月26日 17:36:30 +00:00Commented Apr 26, 2018 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.phtmlfile according to system configuration and also want to update this using custom moduleDeepak Mankotia– Deepak Mankotia2015年11月25日 07:44:10 +00:00Commented Nov 25, 2015 at 7:44 -
@KAndy would you mind clarifying where the statement "action node is deprecated is coming from" - after a quick search of the current core code base I found 4 uses with referenceBlock changing the template . All 4 of them use the action node to set a template and none this approach.Kristof at Fooman– Kristof at Fooman2016年03月09日 10:18:36 +00:00Commented Mar 9, 2016 at 10:18
-
4Thanks - 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 advertisedKristof at Fooman– Kristof at Fooman2016年03月21日 10:27:26 +00:00Commented Mar 21, 2016 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– maginfortis2016年05月24日 08:52:24 +00:00Commented May 24, 2016 at 8:52 -
2This doesn't work. Accepted answer does though.Milan Simek– Milan Simek2017年08月20日 22:20:48 +00:00Commented Aug 20, 2017 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 a 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– Ben Crook2018年05月25日 16:02:13 +00:00Commented May 25, 2018 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.
-
1This is exactly the same piece of code as Aivoris’ answer above.bfontaine– bfontaine2021年03月26日 15:11:41 +00:00Commented Mar 26, 2021 at 15:11