Learn how to implement a custom UI for Landing Page block configuration popup

Studio is a great tool for creating and managing Landing Pages. One of its most powerful features is a possibility to create custom Landing Page blocks with custom functionalities. In a previous tutorial about extending Studio with custom landing page blocks we have managed to create a new Landing Page block whose configuration is derived from PHP files, but the block configuration UI uses the default JS view designed for Landing Page blocks.

During the Web Summercamp 2016 in Rovinj, me and my colleague Kamil Musiał prepared a workshop about extending Studio with blocks that require a custom configuration user interface. In this tutorial, I'm going to provide you all the information required to build such an interface in writing.

Creating custom block UI views using Javascript

Assuming that you already have an existing Studio Landing Page block we can move further to start creating the block's custom configuration user interface. Doing that will require several steps:

  1. Creating a JS plugin to add a custom block JS view to the Studio app,
  2. Creating a custom block JS view that implements a custom configuration popup interface,
  3. Creating a custom block configuration popup JS view with custom interface implemented,
  4. Optionally, creating a JS plugin to manage data required for your interface, e.g. getting information from external resources or making additional requests using REST API to fetch required data based on user interaction in the configuration popup,
  5. Optionally, custom CSS styling,
  6. Finally, the JS dependencies configuration.

In this article you will see the full code example which creates a Twitter post embed block for Landing Pages. The block's config form will allow editors to load a specified user's timeline and will provide the ability of selecting a tweet from the timeline for rendering the preview.

Create a plugin to add your custom block JS view to Studio app

We are going to do it by creating a Javascript plugin for Landing Page Creator JS views. The file with the plugin will be located under Resources/public/js/plugins and will be named as my-add-block-plugin.js. Here's the sample piece of code:

// Resources/public/js/plugins/my-add-block-plugin.js
YUI.add('my-add-block-plugin', function (Y) {
    'use strict';

    Y.namespace('my.Plugin');

    var PLUGIN_NAME = 'myAddBlockPlugin',
        VIEWS = [
            'landingPageCreatorView',
            'dynamicLandingPageCreatorView',
            'dynamicLandingPageEditorView'
        ];

    Y.my.Plugin.AddBlock = Y.Base.create(PLUGIN_NAME, Y.Plugin.Base, [], {
        initializer: function () {
            this.get('host').addBlock('custom', Y.my.BlockView);
        },
    }, {
        NS: PLUGIN_NAME
    });

    Y.eZ.PluginRegistry.registerPlugin(Y.my.Plugin.AddBlock, VIEWS);
});
my-add-block-plugin.js

This plugin does one thing: it adds a new block reference to Studio app. It adds a reference to Y.my.BlockView JS class that is located under the key custom. It's very important to use exactly the same name as a block type defined in your custom block PHP definition - BlockDefinition. In our case the PHP definition is located in the file Block/CustomBlock.php.

Create your custom block JS view

The view is going to be very simple. For our needs it will not implement any custom functionalities to the block view itself. We'll focus only on applying the custom config interface later in this article. The block's JS view should be placed in Resources/public/js/blocks/my-custom-blockview.js

// Resources/public/js/blocks/my-custom-blockview.js
YUI.add('my-custom-blockview', function (Y) {
    'use strict';

    Y.namespace('my');

    Y.my.CustomBlockView = Y.Base.create('myCustomBlockView', Y.eZS.BlockView, [], {
    }, {
        ATTRS: {
            viewClassName: {
                value: 'my.CustomBlockView',
                readOnly: true
            },

            editForm: {
                valueFn: function () {
                    return new Y.my.CustomBlockConfigFormView();
                }
            }
        }
    });
});
my-custom-blockview.js

In the view I redefined the values of two view attributes: viewClassName and editForm. These attributes have to be set in every block view or the app will not be able to detect a correct view and implement a custom config user interface. The custom config view is defined as a value of the editForm attribute. In this case, it's the instance of Y.my.CustomBlockConfigFormView.

Create a custom block config popup view

The next thing is to create a custom config form JS view. The basic example looks like the following:

// Resources/public/js/config-forms/my-customblock-configformview.js
YUI.add('my-customblock-configformview', function (Y) {
    'use strict';

    Y.namespace('my');

    Y.my.CustomBlockConfigFormView = Y.Base.create('myCustomBlockConfigFormView', Y.eZS.BlockPopupFormView, [], {
        initializer: function () {
            this.get('container').addClass(this._generateViewClassName(Y.eZS.BlockPopupFormView.NAME));
        },
    }, {
        ATTRS: {}
    });
});
my-customblock-configformview.js

It should be placed in Resources/public/js/config-forms/my-customblock-configformview.js.

Create custom block config view template

Every JS view in Studio requires a template. The same rule applies to our custom config view. The block we are implementing requires some HTML additions that extend the block's config functionalities by adding a container for an additional content.

<!-- Resources/public/templates/config-forms/custom-blockconfig.hbt -->
<form class="ezs-form pure-form my-custom-form">
    <h3 class="ezs-form__title">{{ title }}</h1>
    <p class="ezs-form__desc">{{ description }}</p>
    <fieldset class="ezs-form__fields pure-group"></fieldset>
    <div class="my-custom-form__tweets"></div>
    <div class="ezs-form__btns">
        <a href="#" class="ezs-form__btn--cancel">Cancel</a>
        <button class="ezs-form__btn--submit" type="submit">Submit</button>
        <button class="ezs-form__btn--close" type="button">Close</button>
    </div>
</form>
custom-blockconfig.hbt

Create JS dependencies config in yui.yml file

The last thing you have to do is to create a Javascript dependencies configuration file located in Resources/config/yui.yml. This file describes the connections between JS modules and declares which modules are required by other modules.

# Resources/config/yui.yml
system:
    default:
        yui:
            combine: true
            modules:
                my-add-customblockview-plugin:
                    requires: ['plugin', 'my-custom-blockview', 'ez-pluginregistry']
                    dependencyOf:
                        - 'ezs-landingpagecreatorview'
                        - 'ezs-dynamiclandingpagecreatorview'
                        - 'ezs-dynamiclandingpageeditorview'
                    path: %my_custom_block.public_dir%/js/plugins/my-add-customblockview-plugin.js
                my-custom-blockview:
                    requires:
                        - 'ezs-blockview'
                        - 'my-customblock-configformview'
                        - 'mycustomblockview-ez-template'
                    path: %my_custom_block.public_dir%/js/blocks/my-custom-blockview.js
                mycustomblockview-ez-template:
                    type: 'template'
                    path: %ezstudioui.public_dir%/templates/blocks/block.hbt
                my-customblock-configformview:
                    requires:
                        - 'ezs-blockpopupformview'
                        - 'mycustomblockconfigformview-ez-template'
                    path: %my_custom_block.public_dir%/js/config-forms/my-customblock-configformview.js
                mycustomblockconfigformview-ez-template:
                    type: 'template'
                    path: %my_custom_block.public_dir%/templates/config-forms/custom-blockconfig.hbt
yui.yml

Summary

These are the basics of creating the custom block configuration forms. Every time you create a block you have to define:

  • Landing Page Creator view plugin that adds a block,
  • custom block view,
  • custom block config view,
  • custom block config template,
  • JS dependencies config.

Code examples

If you want to test a working example, please check the code from Github repository block-bundle on Github.com

 

Leave us a comment
blog comments powered by Disqus