2

Let's talk abstract: I have a certain parameter which determines wether or not the customer account dashboard navigation should be shown on a page or not.

My CMS page has the layout '2 columns left' and I use a plugin/interceptor to try to manipulate the layout.

In short, when I add a cms_page_view.xml to my module, and add the following, the navigation is shown:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="customer_account" />
</page>

Of course, this will add the customer dashboard navigation to all CMS pages, and I only want this to be visible on some pages. So currently I'm using a plugin to wrap around the \Magento\Cms\Controller\Page\View::execute()-method:

public function aroundExecute(\Magento\Cms\Controller\Page\View $subject, callable $proceed)
{
    $pageId = $subject->getRequest()->getParam('page_id', $subject->getRequest()->getParam('id', false));

    /** @var \Magento\Framework\View\Result\Page $resultPage */
    $resultPage = $proceed();

    // Some code that determines whether or not this CMS page should have the dashboard navigation:
    if ( ... ) {
        // Add customer_account layout update:
        // This is the part that doesn't work...
        $resultPage->getLayout()->getUpdate()->addUpdate('customer_account');
    }

    return $resultPage;
}

Why doesn't this work and how can I make it work? An interesting sidenote is that if I add a layout update in the admin with the following:

<update handle="customer_account" />

It also doesn't work. Any thoughts on this matter anyone? I'm using Magento 2.1.3

1 Answer 1

1

I found my answer in this article.

I ended up by creating an event that listens to layout_load_before and inject my layout update in the observer:

class LayoutLoadBefore implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Magento\Framework\App\Request\Http
     */
    protected $request;

    /**
     * LayoutLoadBefore constructor.
     */
    public function __construct(
        \Magento\Framework\App\Request\Http $request
    ) {
        $this->request = $request;
    }

    /**
     * @param Observer $observer
     * @return mixed
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $action = $observer->getData('full_action_name');

        if ($action != 'cms_page_view') {
            return $this;
        }

        $pageId = $this->request->getParam('page_id', $this->request->getParam('id', false));

        // Method that checks if $pageId needs to have the customer_account layout update:
        if (...) {
            $layout = $observer->getData('layout');
            $layout->getUpdate()->addHandle('customer_account');
        }

        return $this;
    }
}

I hope this helps someone. I've already spent way too much time on this one! ;-)

1
  • Thank you so much for this! It helps a lot indeed :) I just would like to give the current CMS page, which is a custom link in the customer menu, the "active" state in the menu itself. Do you know how to achieve that? Commented Oct 7, 2020 at 14:43

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.