Mage-OS PageBuilder Widget module (part of the mage-os release since 2.0 version) allows the user to specify CMS widgets and relative configurations inside a dedicated page builder component named "CMS Widget". As for all pagebuilder components this component is draggable and can be placed inside other components. The main thing about this module is that with it people are now able to configure widgets and see the relative preview on the pagebuilder. IMO, in terms of dev experience enhancement, this is a revolutionary module that erase the necessity to develop page builder dedicated components and understand all the stuff behind (uiComponents, pagebuilder inherit logics,preview vs actual frontend representation). So, the main goal of the module is simplify the development, customization and usage of pagebuilder UI components relying completely on CMS widgets (that are quite easy to use).
The module make the preview management transparent to the developer. All we need to do in order to play with our already developed CMS widgets inside pagebuilder is change the xsi:noNamespaceSchemaLocation inside widget.xml file or create a new module that requires the module that declare these widgets inside it's sequence node of the module.xml file. So... here it is an example: << We have a cms widgets named "my_awesome_slideshow" inside "Vendor_Widget" module and we want to use it on pagebuilder. >>
- Create a new module called "Vendor_WidgetPreview" (or something like that) with these files inside:
--- etc/
------ module.xml
------ widget.xml
- Specify the dependencies inside module.xml file:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_WidgetPreview">
<sequence>
<module name="MageOS_PageBuilderWidget"/>
<module name="Vendor_Widget"/>
</sequence>
</module>
</config>
- Specify widget.xml file with correct schema location and customize it to realize the preview:
<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:MageOS_PageBuilderWidget:etc/widget.xsd">
<widget id="my_awesome_slideshow">
...
</widget>
</widgets>
So from there we're able to work on preview and we have different tools to use.
The first thing is specify witch phtml will be used to produce our preview. And this instruction is the right place to specify it. So, again, inside the "Vendor_WidgetPreview" widget.xml we can specify the right templates:
<widget id="my_awesome_slideshow">
<previewTemplates>
<previewTemplate name="my_frontend_path/default.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/default.phtml</previewTemplate>
<previewTemplate name="my_advanced_frontend_path/advanced.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/advanced.phtml</previewTemplate>
</previewTemplates>
</widget>
We can have multiple templates assigned to our widget so we need to declare the dedicated preview template for each path. For example inside our widget we should see something like that inside one of the "parameter" nodes:
...
<parameter name="template" type="select" visible="true" translate="label">
<label>Template</label>
<option name="default" value="my_frontend_path/default.phtml" selected="true" translate="label">
<label>Default template</label>
</option>
<option name="advanced" value="my_advanced_frontend_path/advanced.phtml" translate="label">
<label>Advanced Template</label>
</option>
</parameter>
...
So, it's important to specify the correct "name" attribute value for previewTemplate tag using the same string used on the main widget.xml "value" attribute of option tag. Now preview phtml files must be placed inside adminhtml folder of the module:
--- etc/
------ module.xml
------ widget.xml
--- view/
------ adminhtml/
--------- my_frontend_path/
------------ default.phtml
--------- my_advanced_frontend_path
------------ advanced.phtml
If you're realizing a new widget a suggestion is to place the template phtml file inside "base" folder so i can be used for both preview and main frontend template. Normally we don't need to have differences between phtmls, maybe is more common to need different Block classes behind.
<widget id="my_awesome_slideshow">
<previewTemplates>
<previewTemplate name="my_frontend_path/default.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/default.phtml</previewTemplate>
<previewTemplate name="my_advanced_frontend_path/advanced.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/advanced.phtml</previewTemplate>
</previewTemplates>
<previewBlock>Vendor\WidgetPreview\Block\Adminhtml\Widget\Preview\MyPreviewBlock</previewBlock>
...
</widget>
As described before the Block class used for the frontend may differ from the class used for the adminhtml preview, mainly because some depencencies can't be used on adminhtml area. So, the instruction and the example above show you how to specify a different Block class.
If we're extending a module that already specify the preview for pagebuilder and we need to make customizations and introduce additional logic we need to extend in the more maintainable way. So, as for the viewModel frontend pattern we can use a similar instruction also on widgets.
<widget id="my_awesome_slideshow">
<previewBlockArguments>
<argument name="viewModel"
xsi:type="object">Vendor\WidgetPreview\ViewModel\Adminhtml\Widget\Preview\MyViewModelPreviewBlock</argument>
</previewBlockArguments>
</widget>
So after specification we're able to use that viewModel inside preview phtml template:
<?php
/** @var Vendor\WidgetPreview\ViewModel\Adminhtml\Widget\Preview\MyViewModelPreviewBlock $viewModelPreview */
$viewModelPreview = $block->getData('viewModel');
...
For every preview this module allow to specify a dedicated CSS file. Inside this file you can style your previews. Keep in mind that these files are included in each widget instance preview on pagebuilder. Be sure to use enough specific css selectors avoiding conflicts with other components and the page outside page pagebuilder stage.
<widget id="my_awesome_slideshow">
<previewTemplates>
<previewTemplate name="my_frontend_path/default.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/default.phtml</previewTemplate>
<previewTemplate name="my_advanced_frontend_path/advanced.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/advanced.phtml</previewTemplate>
</previewTemplates>
...
<previewCss>Vendor_WidgetPreview::css/widget/preview/style_updates.css</previewCss>
...
</widget>
ATTENTION: Remember to place this php snippet inside your phtml preview file for css inclusion
<?= $block->getChildHtml("previewAssets"); ?>
Same thing of PreviewCss can be done for js inclusion. For every preview this module allow to specify a dedicated Js file. Inside this file you can add js actions and triggers to the preview. Remember that mouse actions are not triggered on widgets preview elements so this JS is useful for animations only (ex: sliders scroll, ... )
<widget id="my_awesome_slideshow">
<previewTemplates>
<previewTemplate name="my_frontend_path/default.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/default.phtml</previewTemplate>
<previewTemplate name="my_advanced_frontend_path/advanced.phtml"
xsi:type="string">Vendor_WidgetPreview::preview/advanced.phtml</previewTemplate>
</previewTemplates>
...
<previewJs>Vendor_WidgetPreview/js/my-preview-js-updates</previewJS>
...
</widget>
That's it! We don't need more than phtml, css and js (and the few xml instructions above) to make the pagebuilder able to use our widgets.
Here it is a preview of MageOS_Widgetkit module (still on development).
And the relative widget.xml file:
<?xml version="1.0" ?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:MageOS_PageBuilderWidget:etc/widget.xsd">
<widget id="mageos_slideshow" class="MageOS\Widgetkit\Block\Widgets\Slideshow"
placeholder_image="MageOS_AdvancedWidget::view/frontend/templates/widget/images/slideshow.jpg">
<label translate="true">MageOS Slideshow</label>
<description translate="true">MageOS slideshow widget</description>
<parameters>
<parameter name="template" sort_order="5" xsi:type="select" visible="true">
<label>Template</label>
<options>
<option name="default" value="widget/uikit/slideshow.phtml" selected="true">
<label translate="true">MageOS UIkit themes Slideshow Template</label>
</option>
<option name="magento" value="widget/magento/slideshow.phtml">
<label translate="true">Magento base themes Slideshow Template</label>
</option>
</options>
</parameter>
...
</parameters>
<previewTemplates>
<previewTemplate name="widget/uikit/slideshow.phtml" xsi:type="string">MageOS_Widgetkit::slideshow.phtml</previewTemplate>
<previewTemplate name="widget/magento/slideshow.phtml" xsi:type="string">MageOS_Widgetkit::slideshow.phtml</previewTemplate>
</previewTemplates>
<previewBlock>MageOS\Widgetkit\Block\Adminhtml\Slideshow\Preview</previewBlock>
<previewCss>MageOS_Widgetkit::css/uikit-pagebuilder.css</previewCss>
</widget>
</widgets>