Magento – Render Javascript on customer_login event

blocksevent-observermagento2

I'm trying to render some javascript when the customer_login event fires by accessing a block on the layout from within the observer.

I've successfully registered my observer to execute with the event and that works fine.

The problem I'm running into is that when I attempt to access a specific block object from within the observer the layout does not contain any block elements.

I'm mimicking code that I've seen in the magento2 google analytics plugin that sets a value on a block object from an observer registered on the checkout_onepage_controller_success_action event.

My guess for why this isn't working is that this event fires before any of the block elements are initialized and registered with the layout.

If this is the case and my current approach is not a valid one how would I go about rendering some javascript when this event fires?

etc/frontend/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="customer_login">
        <observer name="login_success" instance="Companyname\Revjs\Observer\SetCompanynameLoginSuccessObserver" />
    </event>
</config>

Observer/SetCompanynameLoginSuccessObserver.php:

<?php

namespace Companyname\Revjs\Observer;

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

class SetCompanynameLoginSuccessObserver implements ObserverInterface
{
    /**
     * @var \Magento\Framework\View\LayoutInterface
     */
    protected $layout;

    /**
     * @param \Magento\Framework\View\LayoutInterface $layout
     */
    public function __construct(
        \Magento\Framework\View\LayoutInterface $layout
    ) {
        $this->layout = $layout;
    }

    public function execute(EventObserver $observer)
    {
        $email = $observer->getEvent()->getCustomer()->getEmail();

        if (!$email) {
            return;
        }

        // this call returns false rather than a block object
        $block = $this->layout->getBlock('companyname');
        $block->setEmail($email);
    }
}

view/frontend/layout/default.xml:

<?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="after.body.start">
            <block class="Companyname\Revjs\Block\Rv" name="companyname" as="companyname" template="rv.phtml"/>
        </referenceContainer>
    </body>
</page>

Block/Rv.php:

namespace Companyname\Revjs\Block;

class Rv extends \Magento\Framework\View\Element\Template
{
    public function getEmailJsFunction()
    {
            $email = $this->getEmail();
            if ($email) {
                    return sprintf("someJsFunction('%s');", $email);
            } else {
                    return '';
            }
    }
}

view/frontend/templates/rv.phtml:

<script>
  <?php echo $block->getEmailJsFunction(); ?>
</script>

Best Answer

you cannot access the blocks in the layout because there are no blocks in the layout.
The customer_login event is dispatched on a POST action that does not have output.
TO overcome this, you can, in your observe, add just something to the session and in you block just check if there is that value in the session.
If there is, use it and remove it.

Related Topic