Magento 2: How to display static block content in modal overlay

Many times we need to show some sort of information in modal overlay when customer comes to the site.
We can use it for many kind of purposes like newsletter subscription form, coupon codes or just some
general information.
In this article I’ll show you how to create the most basic functionality around this.

The challenge

When customer comes to our site, we want to show load specific static block content
into the modal overlay and show it only once to every customer.

Solution:

We should start by creating new module in Magento 2.

For that purpose start by creating app/code/Inchoo/ModalOverlay/registration.php
with following content:

<?php
/**
 * @category    Inchoo
 * @package     Inchoo_ModalOverlay
 * @copyright   Copyright (c) Inchoo (http://inchoo.net/)
 */
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Inchoo_ModalOverlay',
    __DIR__
);

Continue by creating app/code/Inchoo/ModalOverlay/etc/module.xml.
Put the following inside:

<?xml version="1.0"?>
<!--
  @category    Inchoo
  @package     Inchoo_ModalOverlay
  @copyright   Copyright (c) Inchoo (http://inchoo.net/)
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Inchoo_ModalOverlay" setup_version="1.0.0">
    </module>
</config>

That will create a new module in Magento 2.
What we want to do now is to create block that will be shown in modal.
For that purpose, let’s continue by creating another file called
app/code/Inchoo/ModalOverlay/Block/ModalOverlay.php
This one should have the following content:

<?php
 
namespace Inchoo\ModalOverlay\Block;
 
use Magento\Cms\Api\BlockRepositoryInterface;
use Magento\Cms\Api\Data\BlockInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
 
/**
 * Class ModalOverlay
 *
 * @category    Inchoo
 * @package     Inchoo_ModalOverlay
 * @copyright   Copyright (c) Inchoo (http://inchoo.net/)
 */
class ModalOverlay extends Template
{
    /**
     * @var BlockRepositoryInterface
     */
    private $blockRepository;
 
    /**
     * ModalOverlay constructor.
     *
     * @param BlockRepositoryInterface $blockRepository
     * @param Context $context
     * @param array $data
     */
    public function __construct(
        BlockRepositoryInterface $blockRepository,
        Context $context,
        array $data = []
    ) {
        $this->blockRepository = $blockRepository;
 
        parent::__construct($context, $data);
    }
 
    /**
     * Retrieve modal overlay content
     *
     * @param $identifier
     * @return bool|string
     */
    public function getContent($identifier)
    {
        try {
            /** @var BlockInterface $block */
            $block = $this->blockRepository->getById($identifier);
            $content = $block->getContent();
        } catch (LocalizedException $e) {
            $content = false;
        }
 
        return $content;
    }
}

Newly created block needs to have a template, so let’s create it and initialize our JavaScript app/code/Inchoo/ModalOverlay/view/frontend/templates/modal_overlay.phtml

<?php
/**
 * @category    Inchoo
 * @package     Inchoo_ModalOverlay
 * @copyright   Copyright (c) Inchoo (http://inchoo.net/)
 */
?>
<?php /** @var Inchoo\ModalOverlay\Block\ModalOverlay $block */ ?>
<?php if ($content = $block->getContent('this-should-be-renamed')) :?>
<div id="modal-overlay" style="display:none;">
    <?php /* @noEscape */ echo $content ?>
</div>
<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "modal_overlay": {
                        "component": "Inchoo_ModalOverlay/js/modal_overlay"
                    }
                 }
            }
        }
    }
</script>
<?php endif;?>

Let’s add previously created block into layout on every page.
For that purpose, create app/code/Inchoo/ModalOverlay/view/frontend/layout/default.xml and
put the following inside:

<?xml version="1.0"?>
<!--
  @category    Inchoo
  @package     Inchoo_ModalOverlay
  @copyright   Copyright (c) Inchoo (http://inchoo.net/)
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Inchoo\ModalOverlay\Block\ModalOverlay"
                   template="Inchoo_ModalOverlay::modal_overlay.phtml"
                   name="modalOverlay"
                   as="modalOverlay"/>
        </referenceContainer>
    </body>
</page>

And finally, let’s add app/code/Inchoo/ModalOverlay/view/frontend/web/js/modal_overlay.js
with the following content:

/**
 * @category    Inchoo
 * @package     Inchoo_ModalOverlay
 * @copyright   Copyright (c) Inchoo (http://inchoo.net/)
 */
define([
    'uiComponent',
    'jquery',
    'Magento_Ui/js/modal/modal',
    'Magento_Customer/js/customer-data'
], function (Component, $, modal, storage) {
    'use strict';
 
    var cacheKey = 'modal-overlay';
 
    var getData = function () {
        return storage.get(cacheKey)();
    };
 
    var saveData = function (data) {
        storage.set(cacheKey, data);
    };
 
    if ($.isEmptyObject(getData())) {
        var modal_overlay = {
            'modal_overlay': false
        };
        saveData(modal_overlay);
    }
 
    return Component.extend({
 
        initialize: function () {
 
            this._super();
            var options = {
                type: 'popup',
                responsive: true,
                innerScroll: false,
                title: false,
                buttons: false
            };
 
            var modal_overlay_element = $('#modal-overlay');
            var popup = modal(options, modal_overlay_element);
 
            modal_overlay_element.css("display", "block");
 
            this.openModalOverlayModal();
 
        },
 
        openModalOverlayModal:function(){
            var modalContainer = $("#modal-overlay");
 
            if(this.getModalOverlay()) {
               return false;
            }
            this.setModalOverlay(true);
            modalContainer.modal('openModal');
        },
 
        setModalOverlay: function (data) {
            var obj = getData();
            obj.modal_overlay = data;
            saveData(obj);
        },
 
        getModalOverlay: function () {
            return getData().modal_overlay;
        }
 
    });
});

Conclusion

That is it. All that’s left is to create a static block and activate the module.
This should give you a basic module that you can modify however fits you best.

If you want to see how we can help you with these types of custom work on your Magento store, get in touch!


About Tomas Novoselic

Backend Developer

At Inchoo, Tomas is backend developer, Certified Magento Developer who handles Magento modifications at any level. He also works closely with clients on Magento projects of any size and difficulty.

Read more posts by Tomas / Visit Tomas's profile

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.