In this article we’ll learn how to create widgets for Magento 2. Widget allows nicer way to edit/add content inside CMS blocks or page. Through the simple module we’ll show how we can create simple widget.
I guess you know how to create a module, but let me quickly show you step by step.
So, here is the list of files we’ll create:
- app/code/Cookiecode/WidgetBlock/Block/Widget/CustomWidget.php
- app/code/Cookiecode/WidgetBlock/etc/module.xml
- app/code/Cookiecode/WidgetBlock/etc/widget.xml
- app/code/Cookiecode/WidgetBlock/Model/Config/Source/WidgetWidth.php
- app/code/Cookiecode/WidgetBlock/view/adminhtml/web/images/widget_block.png
- app/code/Cookiecode/WidgetBlock/view/frontend/templates/widget/custom_widget.phtml
- app/code/Cookiecode/WidgetBlock/registration.php
The name of our module is “WidgetBlock”. So, let’s start as usual with “registration.php” and “module.xml”.
registration.php
1 2 3 4 5 |
<?php use \Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Cookiecode_WidgetBlock', __DIR__); |
etc/module.xml
1 2 3 4 |
<?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="Cookiecode_WidgetBlock" setup_version="1.0.0" /> </config> |
Next, we’ll create “etc/widget.xml” and add our widget fields. Let’s see structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?xml version="1.0" encoding="UTF-8"?> <widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd"> <widget id="cc_custom_widget" class="Cookiecode\WidgetBlock\Block\Widget\CustomWidget" placeholder_image="Cookiecode_WidgetBlock::images/widget_block.png"> <label translate="true">Cookiecode - Custom block widget</label> <description>Cookiecode - Demo Block widget</description> <parameters> <parameter name="cc_title" xsi:type="text" visible="true" required="true" sort_order="0" > <label translate="true">Title</label> </parameter> <parameter name="cc_content" xsi:type="textarea" visible="true" sort_order="10"> <label translate="true">Widget content</label> </parameter> <parameter name="cc_enable_url" xsi:type="select" visible="true" source_model="Magento\Config\Model\Config\Source\Yesno" sort_order="20"> <label translate="true">Add URL like</label> <description>Enable or disable link</description> </parameter> <parameter name="cc_url" xsi:type="text" visible="true" sort_order="30"> <label translate="true">URL</label> <depends> <parameter name="cc_enable_url" value="1" /> </depends> </parameter> <parameter name="cc_url_label" xsi:type="text" visible="true" sort_order="40"> <label translate="true">URL Label</label> <depends> <parameter name="cc_enable_url" value="1" /> </depends> </parameter> <parameter name="cc_width" xsi:type="select" source_model="Cookiecode\WidgetBlock\Model\Config\Source\WidgetWidth" visible="true" sort_order="50" > <label translate="true">Widget width</label> </parameter> <parameter name="cc_aligment" xsi:type="select" visible="true" sort_order="70" > <label translate="true">Widget aligment</label> <options> <option name="left" value="left" selected="true"> <label translate="true">Left</label> </option> <option name="right" value="right"> <label translate="true">Right</label> </option> </options> </parameter> </parameters> </widget> </widgets> |
The structure of this file is very readable, but we’ll explain some parts of above code.
Tag “widget” contains block class “Cookiecode\WidgetBlock\Block\Widget\CustomWidget” this class is decelerate within “Block/Widget/CustomWidget.php”. The class instructs our widget which template to use.
Attribute “placeholder_image” called the image which is visible when you add widget to content. See the image
More less structure of parameters/fields is very similar to store configuration xml.
For example, we can add custom options inside select or multi-select parameters:
1 2 3 |
<parameter name="cc_width" xsi:type="select" source_model="Cookiecode\WidgetBlock\Model\Config\Source\WidgetWidth" visible="true" sort_order="50" > <label translate="true">Widget width</label> </parameter> |
Code above called source model with custom options. We’ll see this model after. However inside widget we can define custom options easier. Let me show you how:
1 2 3 4 5 6 7 8 9 10 11 |
<parameter name="cc_aligment" xsi:type="select" visible="true" sort_order="70" > <label translate="true">Widget aligment</label> <options> <option name="left" value="left" selected="true"> <label translate="true">Left</label> </option> <option name="right" value="right"> <label translate="true">Right</label> </option> </options> </parameter> |
This way we can define option easier, however, if we get some option value from database in this case we’d need to use source model way to show it.
Next we’ll show how we can define source model WidgetWidth.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php namespace Cookiecode\WidgetBlock\Model\Config\Source; class WidgetWidth implements \Magento\Framework\Option\ArrayInterface { public function toOptionArray() { return [ ['value' => '100%', 'label' => __('100%')], ['value' => '75%', 'label' => __('75%')], ['value' => '50%', 'label' => __('50%')], ['value' => '25%', 'label' => __('25%')]]; } } |
Next snippet of code shows how to define a block for the widget. We’ll define construct which inherits parent construct of magneto default block interface, and we’ll set our template here. Let’s see how it looks.
1 2 3 4 5 6 7 8 9 10 11 |
<?php namespace Cookiecode\WidgetBlock\Block\Widget; class CustomWidget extends \Magento\Framework\View\Element\Template implements \Magento\Widget\Block\BlockInterface { protected function _construct() { parent::_construct(); $this->setTemplate('widget/custom_widget.phtml'); } } |
Next, we’ll see what contain our widget template “custom_widget.phtml”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<style> .cc-custom-widget { background: #ff0; padding: 30px; border-radius: 5px; width: <?php echo $this->getData('cc_width') ?>; align: <?php echo $this->getData('cc_aligment') ?>; } </style> <div class="cc-custom-widget"> <h1><?php echo $this->getData('cc_title'); ?></h1> <?php if ($cc_content = $this->getData('cc_content')): ?> <p><?php echo $cc_content; ?></p> <?php endif; ?> <?php if ($this->getData('cc_enable_url')): ?> <?php $cc_url = $this->getData('cc_url') ?> <?php if (filter_var($cc_url, FILTER_VALIDATE_URL)): ?> <a href="<?php echo $this->getData('cc_url'); ?>"><?php echo $this->getData('cc_url_label'); ?></a> <?php endif; ?> <?php endif; ?> </div> |
Here you can see how to pick up the value form widget parameters. It’s very simple “$this->getData(‘cc_content’)”.
What is our result? Let me show you how it looks inside Magneto Admin. When you try to add our widget called “Cookiecode – Demo Block widget” you’ll see this:
Regarding our example we’ll create page called “Cookiecode demo page” and add the widget into the content. After saving the changes, we can see our widget on the frontend.
Hope this helps, throughout this article we’ve learned how to create simple widget and use it in Magento. Inside widget we can implement great deal of functionality, but it will be explained in some of the future articles.
Here you can download this quick module.
https://github.com/mtunukovic/Cookiecode_WidgetBlock
Enjoy!
Hi,
Suppose i want the widget to be like the category list widget BUT not showing the name but the pic from the category?
What should i do?
Hi Ed,
that scenario should be pretty easy. You need load category collection within your template and show image of category if it exists. I will try to write article on similar theme, following months.
xsi:type=”textarea” that you’re using for cc_content is invalid XML. How should I solve it if I want a textarea (or even better: a WYSIWYG)? Any idea?
Hi,
Did you find a solution for your problem I have the same here.
Thanks
Superb very useful post thank you buddy
Since we declare the template in the Block, how can we dynamically let the user choose which template should be used, without losing the access to $this?
Like, something like:
$this->setTemplate($this->getData(‘template’));
When having a select with the name “template” where its values are the paths to the desired template.
And yes, nine times through ten, somebody on a business enterprise network is
trying to sell something Harmon Discount Coupon Choices begin our organizing voyage great wolf
lodge discount coupons So the following thing I’m going
to inform you discount contact lenses coupon What each and every
know – and stay to surmise – will be the race
of your suspects coupon codes
Hi. thnaks for this tutorial.
However, on Magento 2.1, the new widget didn’t appear on the choice list…(i ‘ve downloaded the master from git)…any idea ?
thanks