Using Magento 2 UI for constructing custom user interface

Magento 2

The only obstacle stopping most developers is Javascript-based robust interface hard implementation process. Therefore, it was featured in very few extensions for Magento and in most cases required additional third-party libraries making extension more difficult to support.

But this situation has dramatically changed with launching Magento 2. The release comes with a comprehensive set of tools to build Javascript-based interface with it’s own widgets and possibility to combine and extend them easily. This is called Magento UI.

Let’s explore, how it works basing on a simple task: display attention window by the button click.

Simple UI Widget with RequireJS

To solve this task we need a widget for a modal dialog window, and also jQuery library working. So now we need to check, whether they are loaded to the page, where we are constructing our preview interface.

This is when Asynchronous Module Definition (AMD) enters the arena. The upshot is allowing developers to load Javascript module on-demand and avoid dependency-connected issues, like loading module before the relied library module.

Magento 2 has built-in support of one the best Javascript AMD framework – RequireJS. This framework features two new keywords – define and require.

Define is used mainly for complex javascripts, extending modules or even for creation the new objects. The other keyword – require – may be called anywhere, even directly from the page. It performs dependency check, but instead of creating an object or a module, it just runs an enclosed code, if the check was successful. Detailed description for both of them, as well as in-depth examples, can be found here.

require(["jquery"],
    function($) {
        alert($('#container').text());
    }
);

Listing 1. Require syntax

As seen in this code, require consists of two arguments – a check for a jQuery library and an anonymous function receiving a global variable to use inside. When page is loaded, require commands browser to check, whether jQuery library is loaded, and if it’s not loaded, it tries to load it asynchronously. If the library loading fails, it will return without any actions. But if jQuery is loaded successfully, the code inside the anonymous function will be immediately executed, e.q. alert message will be displayed.

Therefore, for Magento UI scripting we will use require keyword, as our code will be located directly on the page and should be run immediately after all requirements are met.

Now let’s add to the backend page alert.phtml our button and layer-container for a message to display:

<div id="modal">
    <div id="msg" style="display: none">Modal contents</div>
    <button class="modalRun">Run action</button>
</div>

Listing 2. Template for an attention window

Note, that inner layer has an invisible style. It is used as a container for a message, which will be displayed only on the button click. We can take the code from the Listing 1, and add there the button click handler:

require([
     'jquery',
     'Magento_Ui/js/modal/alert'
     ],
     function($, alert) {
          $('#modal').on('click', 'button.modalRun', function(event){
               event.preventDefault();
               alert({
                    content: $(event.target).parent().children('#msg').text()
               })
          })
     }
);

Listing 3. Script to display a simple attention dialogue

There are two dependencies:

  1. jQuery (since we use it to access our message);
  2. Alert widget module.

Note, that in the listeners we need to use event.preventDefault() call. This will prevent the button from the default action (submitting a form, for example), and we could be ensured, that the listener’s code will be executed.

The attention window is an override of the standard JavaScript alert function by the Magento UI Alert widget. Therefore, instead of a simple string, as shown in the previous listing, we pass there an anonymous object with the content property containing the message itself, which we obtained through the jQuery expression from msg layer.

This script we should place to the separate alert-test.js and add to the template using layout XML file to the head section:

<page xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
      layout="admin-1column">
    <head>
        <script src="Mirasvit_Example::js/alert-test.js"/>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="Mirasvit\Example\Block\Adminhtml\Alert" name="example_alert" template="alert.phtml">
            </block>
        </referenceContainer>
    </body>
</page>

Listing 4. Layout for Alert widget example.

Now let’s clear the cache and re-generate the static content to melt these modules together with your extension.

Therefore, backend user will see the button Run Action, by clicking on which he will receive a message with hidden layer’s content.

Here is how it should look like:

Attention pop up message

Figure 1: Attention popup message

Short Summary

And this is it! We have just created the attention popup with a few simple lines of code.

Of course, we considered the only one of the components, featured in Magento UI library. Using other widgets and their combinations, we can create much more complex user interface. Furthermore, we can even extend these components using RequireJS methods.

But these topics will, probably, be covered in the future articles.

Compatibility issue: adding RequireJS to the layout

The method, described in this article, works not only in the backend, but in the frontend as well. Usually, RequireJS is enabled by default in the most Magento 2 themes, but if it’s not activated, you need to add the following block to the head section in the layout XML file.

<referenceBlock name="head">
     <block class="Magento\Theme\Block\Html\Head\Script" name="requirejs" before="-">
          <arguments>
               <argument name="file" xsi:type="string">requirejs/require.js</argument>
          </arguments>
     </block>
     <block class="Magento\RequireJs\Block\Html\Head\Config" name="requirejs-config" after="requirejs"/>
</referenceBlock>

Listing 5. Adding RequireJS explicitly

This will add RequireJS to the frontend forcibly and Magento UI should work properly.

Ready-to-deploy project with this example is available from our Github.

Enjoyed the Read?

Don’t miss our next article!