So we have a module which has to return a specific view using a layout. However we can not get an empty page rendered to add my layout too.

So our code does the following:

We have a massaction that redirects us to a custom URL order/massAction and that works. On that URL we load the following layout 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" layout="empty">

    <block class="Magento\Framework\View\Element\Template" name="Preview" template="Vendor_Module::order/view.phtml"/>

Setting the layout to empty causes the sidemenu to be loaded and the body to not be loaded, leaving the layout attribute of the page element empty makes it load the body but with a lot of other stuff.

The order/view.phtml is as follows:


<h1>Isn't HTML amazing?</h1>

There is very minimal HTML in the phtml so I /doubt/ that would be the issue. When using template hinting I can't see the block being loaded at all.

The controller we use to do the redirect and layout rendering is as follows:



namespace ***\***\Controller\Adminhtml\Order;

use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Backend\App\Action;
use ***\***\Model\Label;

class MassAction extends Action
    // Objects
    protected $resource;
    protected $pageFactory;
    protected $collectionFactory;
    protected $label;
    protected $filter;

    // Class vars
    public $orderIds = array();

    public function __construct(
        Context $context,
        PageFactory $pageFactory,
        CollectionFactory $collectionFactory,
        Filter $filter,
        Label $label
    ) {
        $this->pageFactory = $pageFactory;
        $this->collectionFactory = $collectionFactory;
        $this->filter = $filter;
        $this->label    = $label;

    public function _isAllowed()
        return $this->_authorization->isAllowed('Vendor::module');

    public function execute()

        $pageObject = $this->pageFactory->create();

        return $pageObject;

    public function getOrderIds()
        $collection = $this->filter->getCollection($this->collectionFactory->create());
        foreach ($collection->getItems() as $order) {
            $this->orderIds[] = $order->getId();
        return $this->orderIds;

This appears to be working except weird stuff is being printed out rather than our layout + view. If anyone knows what we are doing wrong it is greatly appriciated.

PLEASE READ: The vendor name and module name have been altered in the code. Where possible Vendor/Module is being used and where not possible due to the possibility of confusion ***/*** is being used.

  • try recreate your module controller in mage2gen.com Commented Jul 20, 2018 at 9:59
  • @TinyDancer thanks for the suggestion, I tried but it was lacking layout/massaction functionality in the end it didn't work even with the generated module. Commented Jul 20, 2018 at 10:18

1 Answer 1


The issue was in the layout.xml file.

First issue was that we set a layout to empty, which ironically isn't empty.

Second issue was that we were trying to get a body rather than to overwrite the "main" container.

The proper xml file is as follows:


<?xml version="1.0"?>
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
    <container name="root">
        <block class="Vendor\Module\Block\Adminhtml\Preview" name="Preview" template="Vendor_Module::order/view.phtml" />

By overriding the root container we can add our block to nothing but an empty page.

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.