Magento – Magento 2. Call .phtml (modal) from observer

custom-templatemagento2.2.2modal-popup

I have created a custom .phtml file that contains a modal popup.

I can successfully call this .phtml by adding it to default.xml in layout.

<?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>
        <referenceContainer name="root">'
            <block class="Magento\Store\Block\Switcher" name="redirectPopup" template="Magento_Store::switch/redirectPopup.phtml" />
        </referenceContainer>
    </body>
</page>

The code above working fine.

But I would like to call this template only if a certain condition is matched. That's why I want to call it from observer in my custom module.

I tried the following code in observer,

public function showRedirectPopup()
{
    $block = $this->layout->createBlock('Magento\Store\Block\Switcher')->setTemplate('Magento_Store::switch/redirectPopup.phtml')->toHtml();
    return $block;
}

I have made sure the function showRedirectPopup() is executed. But it doesn't seems .phtml is being called.

Did I miss anything?

Can we at all call a .phtml from a observer or it has to be called from layout(.xml)?

Best Answer

Could you check if your script injects

\Magento\Framework\View\LayoutFactory $layoutFactory

in the constructor.

After that in your execute function place this:

$layout = $this->layoutFactory->create();
$block = $layout->createBlock('Magento\Store\Block\Switcher')->setTemplate('Magento_Store::switch/redirectPopup.phtml')->toHtml();
return $block;

Now it should work

EDIT:

i see what i missed in my answer. Forgot to tell that you must set the response header and body, instead of returning the html directly. So it goes like this:

$block = $layout->createBlock('Magento\Store\Block\Switcher')->setTemplate('Magento_Store::switch/redirectPopup.phtml');
$response = $observer->getEvent()->getData('response');
$response
    ->setHeader('Content-Type','text/html')
    ->setBody($block->toHtml());
return; 

Also make sure you pick an event that is fired later than controller_action_predispatch for example controller_front_send_response_before because the response object doesn't exist yet. Using this object the right response type can be set