I want to remove a block from the layout in magento 2 that is declared in a third party extension, but the block does not have a name.
Can I do that?

The block is declared like this

<referenceContainer name="before.body.end">
    <block class="Magento\Backend\Block\Template" template="[Vendor_Module]::template.phtml"/>

I cannot use

<referenceBlock name="..." remove="true" /> 

because, as you can see there is no name on it.

  • marius, i have idea.if we using event and remove block by match template name [Vendor_Module]::template.phtml
    – Amit Bera
    Dec 21, 2017 at 11:06
  • I have the same idea (see comments on the answer) but I will use it only as a desperate measure. I was hoping for a simple solution. If you have some code, post it as an answer.
    – Marius
    Dec 21, 2017 at 11:20
  • ha ha that we donot have simple solution.let me try give u an answer using event
    – Amit Bera
    Dec 21, 2017 at 11:27

3 Answers 3


I found this issue in class Magento\Framework\View\Layout\ScheduledStructure\Helper

There is function _generateAnonymousName:

protected function _generateAnonymousName($class)
    $position = strpos($class, '\\Block\\');
    $key = $position !== false ? substr($class, $position + 7) : $class;
    $key = strtolower(trim($key, '_'));
    return $key . $this->counter++;

It's call from scheduleStructure function:

    public function scheduleStructure(
    Layout\ScheduledStructure $scheduledStructure,
    Layout\Element $currentNode,
    Layout\Element $parentNode
) {
    // if it hasn't a name it must be generated
    if (!(string)$currentNode->getAttribute('name')) {
        $name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block'); // CALL HERE
        $currentNode->setAttribute('name', $name);
    $path = $name = (string)$currentNode->getAttribute('name');

    // Prepare scheduled element with default parameters [type, alias, parentName, siblingName, isAfter]
    $row = [
        self::SCHEDULED_STRUCTURE_INDEX_TYPE           => $currentNode->getName(),
        self::SCHEDULED_STRUCTURE_INDEX_ALIAS          => '',
        self::SCHEDULED_STRUCTURE_INDEX_IS_AFTER       => true,

    $parentName = $parentNode->getElementName();
    //if this element has a parent element, there must be reset [alias, parentName, siblingName, isAfter]
    if ($parentName) {
        $row[self::SCHEDULED_STRUCTURE_INDEX_ALIAS] = (string)$currentNode->getAttribute('as');
        $row[self::SCHEDULED_STRUCTURE_INDEX_PARENT_NAME] = $parentName;

            $row[self::SCHEDULED_STRUCTURE_INDEX_IS_AFTER]) = $this->_beforeAfterToSibling($currentNode);

        // materialized path for referencing nodes in the plain array of _scheduledStructure
        if ($scheduledStructure->hasPath($parentName)) {
            $path = $scheduledStructure->getPath($parentName) . '/' . $path;

    $this->_overrideElementWorkaround($scheduledStructure, $name, $path);
    $scheduledStructure->setPathElement($name, $path);
    $scheduledStructure->setStructureElement($name, $row);
    return $name;

With this case, Block name can be:

  • before.body.end_schedule_block1
  • before.body.end_schedule_block2
  • ...

I think you should define totals block without the name on container and order block name need remove on the container.

  • I don't think this will work. There is no way to predict the generated name since on different pages there can be multiple blocks added in the body.before.end container in different order.
    – Marius
    Dec 21, 2017 at 10:37
  • This case only applies to block/container without a name. If all of them without the name, so difficult to define some block/container need removed.
    – LinoPham
    Dec 21, 2017 at 10:42
  • yep...my problem exactly
    – Marius
    Dec 21, 2017 at 10:45
  • We should rewrite $name = $this->_generateAnonymousName($parentNode->getElementName() . '_schedule_block'); , Should be pass class & template to parameter ?
    – LinoPham
    Dec 21, 2017 at 10:58
  • 2
    seems like an overhead to rewrite something like that. I'm looking for a simple solution (if any) or an answer like 'not possible very easily'. I think I can observe the layout generate blocks event or something to remove it there, but again seems too much overhead. I'm keeping that as a backup solution.
    – Marius
    Dec 21, 2017 at 11:01

I got an idea from Amit's answer and ended up with a working solution that does not look very intrusive and it's not an overkill since my code is executed only once.

I've created an observer on the event layout_generate_blocks_after that is executed after the layouts are loaded and the blocks are generated.

This can have a drawback because the block I'm trying to remove still gets instantiated, but in my case I just needed to remove it from the page.

So I have the file etc/adminhtml/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="layout_generate_blocks_after">
        <observer name="remove-the-block" instance="[MyVendor]\[MyModule]\Observer\RemoveBlock" />

and my observer class:

namespace [MyVendor]\[MyModule]\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class RemoveBlock implements ObserverInterface
    const TEMPLATE_TO_REMOVE = '[OtherVendor]_[OtherModule]::template.phtml';
    public function execute(Observer $observer)
        /** @var \Magento\Framework\View\Layout $layout */
        $layout = $observer->getLayout();
        $blocks = $layout->getAllBlocks();
        foreach ($blocks as $key => $block) {
            /** @var \Magento\Framework\View\Element\Template $block */
            if ($block->getTemplate() == self::TEMPLATE_TO_REMOVE) {

I am really give u bad idea.

Here the idea is not stop output of your block

Using event view_block_abstract_to_html_after

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="view_block_abstract_to_html_after">
        <observer name="myObserverName" instance="Stack\Work\Observer\MyObserver" />

And using this observer disable output of your block

namespace Stack\Work\Observer;
use Magento\Framework\Event\ObserverInterface;

class MyObserver implements ObserverInterface
  public function __construct()
    //Observer initialization code...
    //You can use dependency injection to get any class this observer may need.

  public function execute(\Magento\Framework\Event\Observer $observer)
    $block = $observer->getData('block');

    if('[Vendor_Module]::template.phtml' == $block->getTemplate()){
        $transport = $observer->getData('transport');

  • this is not actually such a bad idea. Indeed there is an overkill observing all the blocks, but I'm willing to use it over other options. I will try and let you know.
    – Marius
    Dec 22, 2017 at 7:46
  • coool. man.... see what happen
    – Amit Bera
    Dec 22, 2017 at 8:22
  • 1
    It works, but I tried to optimize it a bit, not to execute the code for every block. So I ended up with my answer. Thanks for the idea.
    – Marius
    Dec 22, 2017 at 8:32
  • I see answer, that really good man :)
    – Amit Bera
    Dec 22, 2017 at 8:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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