preloder

Magento 2 Modal Widget in Use

Prev Next

In this article, I will show you how to implement new Module Version field for your Custom Module configuration by using JavaScript Modal Widget component from Magento 2 UI Library.

Overview

Let’s say you want to show module version somewhere on the configuration settings page of a custom module. It might be helpful for Merchants to see and verify an updated version of a custom module. In addition to a module version, we may show release notes for any changes appeared in a release.

The following is an example of Module Version field located in Stores -> Configuration -> Custom Module section.

Module Version and Release Notes link

We also have “Release Notes” link which shows additional information in a popup window. Here is an example:

Realex Payments release notes popup

Alright, let’s go into details and implement Release Notes popup using Modal Widget and custom Module Version field.

Configuration

First of all, we have to declare new “Module Version” field in system.xml configuration file. You may notice from the picture above the “Module Version” field has no scope information. Also, there is no “Use Config” checkbox setting in case “Store View” is used to see “Store” or “Website” specific configuration. Well, version of a module does not depend on scope :).

The “Module Version” field in Pronko\ModuleVersion\etc\adminhtml\system.xml configuration file:

<field id="version" translate="label" type="note" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>Module Version</label>
    <frontend_model>Pronko\ModuleVersion\Block\Adminhtml\System\Config\Version</frontend_model>
</field>

I use “note” type for “Module Version” field in order to say Form renderer to use Magento\Framework\Data\Form\Element\Noteclass. The Note class uses simple <div /> element to render text information. The Magento\Framework\Data\Form\Element\Note::getElementHtml() method uses getText() magic method:

public function getElementHtml()
{
    $html = $this->getBeforeElementHtml()
    . '
<div id="' . $this->getHtmlId()
    . '" class="control-value admin__field-value">'
    . $this->getText()
    . '</div>

'
    . $this->getAfterElementHtml();
    return $html;
}

Frontend Model Class

The Pronko\ModuleVersion\Block\Adminhtml\System\Config\Version class is responsible for preparing module version and “Release Notes” link. Once prepared, information is set to Magento\Framework\Data\Form\Element\Note object using ‘text’ data key. Also, the Version class overrides _renderScopeLabel() and _renderInheritCheckbox() methods in order to remove Scope and Checkbox information from the “Module Version” field.

Here is the implementation of the Pronko\ModuleVersion\Block\Adminhtml\System\Config\Version class:

namespace Pronko\ModuleVersion\Block\Adminhtml\System\Config;

use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Backend\Block\Template\Context;
use Magento\Config\Block\System\Config\Form\Field;
use Pronko\ModuleVersion\Model\ConfigInterface;

/**
 * Backend system config module version field renderer
 */
class Version extends Field
{
    /**
     * @var ConfigInterface
     */
    protected $config;

    /**
     * Version constructor.
     * @param Context $context
     * @param ConfigInterface $config
     * @param array $data
     */
    public function __construct(
        Context $context,
        ConfigInterface $config,
        array $data = []
    ) {
        $this->config = $config;
        parent::__construct($context, $data);
    }

    /**
     * @param AbstractElement $element
     * @return string
     */
    protected function _getElementHtml(AbstractElement $element)
    {
        $html = $this->config->getModuleVersion() .
            ' <a href="#" class="changelog module-version popup" id="custom-release-notes">' .
            __('Release Notes') .
            '</a>';

        $element->setData('text', $html);
        return parent::_getElementHtml($element);
    }

    /**
     * @param AbstractElement $element
     * @return string
     */
    protected function _renderScopeLabel(AbstractElement $element)
    {
        return '';
    }

    /**
     * @param AbstractElement $element
     * @return string
     */
    protected function _renderInheritCheckbox(AbstractElement $element)
    {
        return '';
    }
}

Release Notes Modal Component

Next step is to create Release Notes component which will be responsible for Modal Widget initialization and observing “click” event of the “Release Notes” link. For this tutorial, I am going to hard-code “custom-release-notes” ID of the Release Notes link.

New Release Notes component is located in the Pronko\ModuleVersion\view\adminhtml\web\js\release-notes.js JavaScript file.

define([
    'jquery',
    'Magento_Ui/js/modal/modal'
], function($) {
    'use strict';

    return function (optionsConfig) {
        var releaseNotes = $('<div/>').html(optionsConfig.html).modal({
            modalClass: 'changelog',
            title: $.mage.__('Realex Payments Release Notes'),
            buttons: [{
                text: 'Ok',
                click: function () {
                    this.closeModal();
                }
            }]
        });
        $('#custom-release-notes').on('click', function() {
            releaseNotes.modal('openModal');
        });
    };
});

We are going to pass HTML from backend side. Alternatively, we may create release-notes.html template and pre-populate it in the release-notes.js with information passed from backend.

Release Notes Component Declaration

In order to initialize the release-notes.js componenent it should be added into the adminhtml_system_config_edit.xml layout update.

The declaration is located in the Pronko\ModuleVersion\view\adminhtml\layout\adminhtml_system_config_edit.xml configuration file:

<page>
    <body>
        <referenceContainer name="js">
            <block class="Pronko\ModuleVersion\Block\Adminhtml\System\Config\ReleaseNotes" template="Pronko_ModuleVersion::system/config/release-notes.phtml"/>
        </referenceContainer>
    </body>
</page>

The release-notes.phtml is used to initialize release-notes.js component and pass HTML from the Pronko\ModuleVersion\Block\Adminhtml\System\Config\ReleaseNotes block class.

The Pronko\ModuleVersion\view\adminhtml\templates\system\config\release-notes.phtml file:

<?php /** @var \Pronko\ModuleVersion\Block\Adminhtml\System\Config\ReleaseNotes $block */ ?>
<scri pt type="text/x-magento-init">
{
    "*": {
        "releaseNotes": <?php echo $block->getReleaseNotesJson(); ?>
    }
}
</sc2ript>

The releaseNotes alias is declared in the requirejs-config.js:

var config = {
    map: {
        '*': {
            releaseNotes: 'Pronko_ModuleVersion/js/release-notes'
        }
    } 
};

Release Notes Block

The Pronko\ModuleVersion\Block\Adminhtml\System\Config\ReleaseNotes class prepares and returns HTML which later will be rendered as part of Release Notes Popup.

namespace Pronko\ModuleVersion\Block\Adminhtml\System\Config;

use Magento\Backend\Block\Template;

class ReleaseNotes extends Template
{
    /**
     * @return string
     */
    public function getReleaseNotesJson()
    {
        return json_encode([
            'html' => $this->getContent()
        ]);
    }
}

Feel free to implement getContent() method to return release notes of a custom module.

Final Thoughts

Even if Magento backend has Prototype JavaScript library you are still more than welcome to use jQuery Widgets and Knockout libraries for custom UI behavior. This article shows one of the ways of implementing new Module Version configuration field where version and Release Notes might be presented for a Merchant in a nice and user-friendly manner.

Max Pronko is an international Magento Expert, development consultant, motivational speaker and Magento award-winning developer. He is known for the educational development programs for organizations of all sizes and has positively affected thousands of people and organizations worldwide.

Posted on Jul 10, 2016

The Devletter

Subscribe to my Magento 2 tips and tutorials content.
Every week I send an interesting email directly to your inbox

Related Posts