I have a block class My\Extension\Block\MyClass
which I want to insert into the layout. But I would not be knowing which page to insert in (will be specified by the admin), so I'm observing the layout_render_before
event and in my observer class' execute method I'm doing the following
$allowedBlock = $this->_configModel->getAllowedBlock(); // get the block name where to insert
$allowedAction = $this->_configModel->getAllowedAction(); // get the full action name of the controller where to insert
$layout = $this->_layout;
$action = $this->_request->getFullActionName();
if($allowedAction !== $action) return false; // if current page is not where to insert block, stop further processing
$parentBlock = $layout->getBlock($allowedBlock); // get the block from the layout where to insert
if ($parentBlock) { // if parent block exists
$blockName = 'My\Extension\Block\MyClass';
$blockToInsert = $layout->createBlock($blockName,'my_extensions_unique_block_name'); // create block to insert
$parentBlock->append($blockToInsert); // insert block to parent
}
And in my block I am setting the template like so,
public function _prepareLayout(){
$this->setTemplate('My_Extension::subdirectory/my_template.phtml');
parent::_prepareLayout();
}
And in my template file, I have a very simple string displayed
<h1>Hello World From Template</h1>
This exact code was working in Magento 1.9.x. The only difference was that I used the controller_action_layout_render_before
event instead of layout_render_before
. But the controller_action_layout_render_before
was not working in Magento 2.1.x, so I used the layout_render_before
event instead.
But now, my block is not visible on the frontend, even though if I write some code in my block's constructor (like echo "Hello World From Block's constructor";
) it comes up on the page, meaning the block is being called, but the template is not visible on the frontend.
Considering the fact that the exact same code which was working on Magento 1.9.x, is not working in Magento 2.1.x, what am I doing wrong?
Best Answer
Use plugins. Scroll down for the working solution.
Two issues with your approach:
layout_render_before
is called after layout is rendered. Checkvendor/magento/framework/View/Result/Layout.php
:So you append your block after the block has been rendered.
Magento does not render all block's children. At least not for
vendor/magento/framework/View/Element/Template.php
which is used for almost (correct me if I am wrong here) all blocks. You would have to putecho $this->getChildHtml('name_in_layout')
in all templates.Working solution. Tested in Magento 2.1.4
Use this plugin in your
etc/di.xml
:app/code/Goivvy/Custom/Plugin/InjectPlugin.php
:Instead of
copyright
andcatalog_product_view
use your dynamic block name and full action name.