Ref: https://www.magestore.com/magento-2-tutorial/how-to-create-magento-2-widget/
https://www.cloudways.com/blog/magento-2-custom-widget/
1. Create ‘Contact Informations’ Widget
Create a module directory ‘Advcha_Customwidget’ in app/Advcha/Customwidget
Then create a registration file registration.php in the above directory:
|
1 2 3 4 5 6 |
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Advcha_Customwidget', __DIR__ ); |
Then create the module file module.xml in etc/ directory:
|
1 2 3 4 5 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> <module name="Advcha_Customwidget" setup_version="1.0.0"> </module> </config> |
Then create the backend widget form widget.xml in etc/ directory:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="UTF-8"?> <widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Magento/Widget/etc/widget.xsd"> <widget id="advcha_customwidget_contact" class="Advcha\Customwidget\Block\Widget\ContactInformations"> <label translate="true">Contact Informations Widget</label> <description>Widget in Magento2</description> <parameters> <parameter name="fullname" xsi:type="text" visible="true" sort_order="0" > <label translate="true">Full Name</label> </parameter> <parameter name="age" xsi:type="text" visible="true" sort_order="10" > <label translate="true">Age</label> </parameter> <parameter name="gender" xsi:type="select" source_model="Advcha\Customwidget\Model\Config\Source\Gender" visible="true" sort_order="10" > <label translate="true">Gender</label> </parameter> </parameters> </widget> </widgets> |
Then create the block file Contactinformations.php in Block/Widget/ directory:
|
1 2 3 4 5 6 7 8 9 10 11 |
<?php namespace Advcha\Customwidget\Block\Widget; class ContactInformations extends \Magento\Framework\View\Element\Template implements \Magento\Widget\Block\BlockInterface { /*public function _toHtml() { $this->setTemplate('widget/contact_informations.phtml'); }*/ protected $_template = "widget/contact_informations.phtml"; } |
Create the source file for gender input Gender.php in Model/Config/Source/ directory:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php namespace Advcha\Customwidget\Model\Config\Source; class Gender implements \Magento\Framework\Option\ArrayInterface { public function toOptionArray() { return [ ['value' => 'mal', 'label' => __('Male')], ['value' => 'female', 'label' => __('Female')]]; } } |
Then create the template file to show the widget contact_informations.phtml in view/frontend/templates/widget/ directory:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php $fullname = $this->getData('fullname'); $age = $this->getData('age'); $gender = $this->getData('gender'); ?> <ul> <?php if($fullname){ ?> <li><?php echo $fullname ?></li> <?php } ?> <?php if($age){ ?> <li><?php echo $age ?></li> <?php } ?> <?php if($gender){ ?> <li> <?php if($gender){ echo __('Male'); }else{ echo __('Female'); } ?> </li> <?php } ?> </ul> |
Enable the module: php bin/magento module:enable Advcha_Customwidget
then clear the cache: php bin/magento c:f
I want to display the widget in the homepage. So in the admin page: Content -> Pages,
Find Homepage -> Edit
In Content -> Show/Hide Editor -> Insert Widget -> On the Widget Type dropdown, find ‘Contact Informations Widget’ then fill the options like ‘Full Name’, ‘Age’ and ‘Gender’.
The html widget would be like this:
|
1 |
<p>{{widget type="Advcha\Customwidget\Block\Widget\ContactInformations" fullname="Satria Faestha" age="42" gender="mal" type_name="Contact Informations Widget"}}</p> |
Then Save the page. Also it worth to run the command: php bin/magento c:c && php bin/magento c:f
Then refresh your homepage. It’d show the widget at the bottom (above the footer on the Luma theme).
2. Create ‘Category’ Widget
ref: https://www.dckap.com/blog/create-category-widget-magento-2/
Create a module directory ‘Advcha_Catwidget’ in app/Advcha/Catwidget
Then create a registration file registration.php in the above directory:
|
1 2 3 4 5 6 |
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Advcha_Catwidget', __DIR__ ); |
Then create the module file module.xml in etc/ directory:
|
1 2 3 4 5 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> <module name="Advcha_Catwidget" setup_version="1.0.0"> </module> </config> |
Then create the backend widget form widget.xml in etc/ directory:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="UTF-8"?> <widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Magento/Widget/etc/widget.xsd"> <widget id="advcha_catwidget_contact" class="Advcha\Catwidget\Block\Widget\ShowCats"> <label translate="true">Show Cats Widget</label> <description>Widget in Magento2</description> <parameters> <parameter name="catid" xsi:type="text" visible="true" sort_order="0" > <label translate="true">Master Category Id (type '2' for default top category)</label> </parameter> </parameters> </widget> </widgets> |
Then create the block file ShowCats.php in Block/Widget/ directory:
|
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
<?php namespace Advcha\Catwidget\Block\Widget; use Magento\Widget\Block\BlockInterface; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context; use Magento\Store\Model\StoreManagerInterface; class ShowCats extends Template implements BlockInterface { protected $_template = 'widget/showcategories.phtml'; protected $categoryRepository; protected $_categoryCollectionFactory; protected $_storeManager; public function __construct(Context $context, StoreManagerInterface $storeManager, CollectionFactory $categoryCollectionFactory) { $this->_storeManager = $storeManager; $this->_categoryCollectionFactory = $categoryCollectionFactory; parent::__construct($context); } /** * Get value of widgets' title parameter * * @return mixed|string */ public function getTitle() { return $this->getData('title'); } /** * Retrieve Category ids * * @return string */ public function getCategoryIds() { if ($this->hasData('catid')) { return $this->getData('catid'); } return $this->getData('catid'); } /** * Get the category collection based on the ids * * @return array */ public function getCategoryCollection() { $category_ids = explode(",", $this->getCategoryIds()); $condition = ['in' => array_values($category_ids)]; //$collection = $this->_categoryCollectionFactory->create()->addAttributeToFilter('entity_id', $condition)->addAttributeToSelect(['name', 'is_active', 'parent_id', 'image'])->setStoreId($this->_storeManager->getStore()->getId()); $collection = $this->_categoryCollectionFactory->create()->addAttributeToFilter('entity_id', $condition)->addAttributeToSelect(['name', 'is_active', 'parent_id'])->setStoreId($this->_storeManager->getStore()->getId()); return $collection; } } |
Then create the template file to show the widget showcategories.phtml in view/frontend/templates/widget/ directory:
|
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 |
<?php /** * Category widget * * @var $block \Advcha\Catwidget\Block\Widget\ShowCats */ ?> <?php $title = $block->getTitle() ? __($block->getTitle()) : 'Categories'; ?> <div class="block-title"> <strong role="heading" aria-level="2"><h3><?php /* @escapeNotVerified */ echo $title; ?></h3></strong> </div> <?php $collection = $block->getCategoryCollection(); ?> <ul> <?php foreach ($collection as $category): if (!$category->getIsActive()) { continue; } ?> <select id="master_cats" name="master_cats"> <?php if ($childrenCategories = $category->getChildrenCategories()): ?> <?php foreach ($childrenCategories as $childrenCategory): if (!$childrenCategory->getIsActive()) { continue; } ?> <option value="<?php echo $childrenCategory->getId() ?>"><?php echo $childrenCategory->getName() ?></option> <?php endforeach; endif; ?> </select> <?php endforeach; ?> </ul> |
Enable the module: php bin/magento module:enable Advcha_Catwidget
then clear the cache: php bin/magento c:f OR RUN THE FULL COMMAND:
|
1 |
php bin/magento setup:upgrade --keep-generated && php bin/magento setup:di:compile && php bin/magento setup:static-content:deploy -f --language en_AU --language en_US && php bin/magento indexer:reindex && php bin/magento cache:clean && php bin/magento cache:flush |
I want to display the widget in the homepage. So in the admin page: Content -> Pages,
Find Homepage -> Edit
In Content -> Show/Hide Editor -> Insert Widget -> On the Widget Type dropdown, find ‘Contact Informations Widget’ then fill the options like ‘Master Category Id (type ‘2’ for default top category)’. For the default top category, please type: 2
The html widget would be like this:
|
1 |
<p>{{widget type="Advcha\Catwidget\Block\Widget\ShowCats" catid="2" type_name="Show Cats Widget"}}</p> |
Then Save the page. Also it worth to run the command: php bin/magento c:c && php bin/magento c:f
Then refresh your homepage. It’d show the widget at the bottom (above the footer on the Luma theme).
UPDATED!!!
TO SHOW ALSO THE SUB CATEGORIES, USE AJAX TO REFRESH THE SUB CATEGORIES AND REDIRECT TO THE SEARCH CATEGORY IF THE ANY OF THE CATEGORY AND/OR SUB CATEGORY IS SELECTED!
MODIFY Advcha/Catwidget/Block/Widget/ShowCats.php:
NOTE: I USED ‘Psr\Log\LoggerInterface’ FOR LOGGING BUT IT CAN’T WRITE TO THE LOG FILE SO I USED Zend Log ($writer = new \Zend\Log\Writer\Stream(BP . ‘/var/log/collection.log’))
I SAVED THE OLD FUNCTION TO ‘getCategoryCollection_old’ AND REPLACE IT WITH ‘getCategoriesCollection’ FUNCTION:
|
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
... //use Psr\Log\LoggerInterface; class ShowCats extends Template implements BlockInterface { //protected $_logger; public function __construct(Context $context, StoreManagerInterface $storeManager, CollectionFactory $categoryCollectionFactory/*, LoggerInterface $logger*/) { $this->_storeManager = $storeManager; $this->_categoryCollectionFactory = $categoryCollectionFactory; //$this->_logger = $logger; //NOT WORKING parent::__construct($context); } ... /** * Get the category collection based on the ids * * @return array */ public function getCategoryCollection_old() { $category_ids = explode(",", $this->getCategoryIds()); $condition = ['in' => array_values($category_ids)]; //$collection = $this->_categoryCollectionFactory->create()->addAttributeToFilter('entity_id', $condition)->addAttributeToSelect(['name', 'is_active', 'parent_id', 'image'])->setStoreId($this->_storeManager->getStore()->getId()); $collection = $this->_categoryCollectionFactory->create()->addAttributeToFilter('entity_id', $condition)->addAttributeToSelect(['name', 'is_active', 'parent_id'])->setStoreId($this->_storeManager->getStore()->getId()); return $collection; } public function getCategoriesCollection() { //$level = 'DEBUG'; $json = array(); $category_ids = explode(",", $this->getCategoryIds()); $condition = ['in' => array_values($category_ids)]; $collection = $this->_categoryCollectionFactory->create()->addAttributeToFilter('entity_id', $condition)->addAttributeToSelect(['name', 'is_active', 'parent_id'])->setStoreId($this->_storeManager->getStore()->getId()); $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/collection.log'); $this->logger = new \Zend\Log\Logger(); $this->logger->addWriter($writer); $this->logger->info("collection:"); $this->logger->info(print_r(count(array($collection)), true)); //$this->_logger->log($level,'collection', array("OK")); //$this->_logger->addDebug('collection'); //if($collection){ $i = 0; foreach ($collection as $category){ if (!$category->getIsActive()) { continue; } /*$json[] = array( "id" => $category->getId(), "name" => $category->getName(), ); $this->logger->info("cat1:"); $this->logger->info($json);*/ if ($childrenCategories = $category->getChildrenCategories()){ foreach ($childrenCategories as $childrenCategory){ if (!$childrenCategory->getIsActive()) { continue; } $json[$i] = array( "id" => $childrenCategory->getId(), "name" => $childrenCategory->getName(), "url" => $childrenCategory->getUrl(), ); $this->logger->info("cat2:"); $this->logger->info($json); if ($children2Categories = $childrenCategory->getChildrenCategories()){ foreach ($children2Categories as $children2Category){ if (!$children2Category->getIsActive()) { continue; } $json[$i]["children"][] = array( "id" => $children2Category->getId(), "name" => $children2Category->getName(), "url" => $children2Category->getUrl(), ); $this->logger->info("cat3:"); $this->logger->info($json); } } $i++; } } } //} return json_encode($json, JSON_HEX_APOS); } } |
Then modified Advcha/Catwidget/view/frontend/templates/widget/showcategories.phtml:
|
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
<?php /** * Category widget * * @var $block \Advcha\Catwidget\Block\Widget\ShowCats */ ?> <?php $title = $block->getTitle() ? __($block->getTitle()) : 'Categories'; ?> <div class="block-title"> <strong role="heading" aria-level="2"><h3><?php /* @escapeNotVerified */ echo $title; ?></h3></strong> </div> <?php /*$collection = $block->getCategoryCollection(); ?> <ul> <?php foreach ($collection as $category): if (!$category->getIsActive()) { continue; } ?> <select id="master_cats" name="master_cats"> <?php if ($childrenCategories = $category->getChildrenCategories()): ?> <?php foreach ($childrenCategories as $childrenCategory): if (!$childrenCategory->getIsActive()) { continue; } ?> <option value="<?php echo $childrenCategory->getId() ?>"><?php echo $childrenCategory->getName() ?></option> <?php endforeach; endif; ?> </select> </ul> <?php endforeach;*/ //print_r(json_decode($block->getCategoriesCollection())); $collections = $block->getCategoriesCollection(); $collections_decode = json_decode($collections, true); echo '<select id="master_cats" name="master_cats">'; echo '<option value="">---Select Categories---</option>'; foreach($collections_decode as $c){ //echo "c:".$c['id']."<br/>"; echo '<option value="'.$c['id'].'">'.$c['name'].'</option>'; /*foreach($c as $k=>$v){ echo "v:".var_dump($v)."<br/>"; //echo '<option value="'.$v['id'].'">'.$v['name'].'</option>'; }*/ } echo '</select>'; echo '<br/><strong>Sub Categories</strong>'; echo '<select id="child_cats" name="child_cats">'; echo '<option value="">---Select Sub Categories---</option>'; echo '</select>'; echo '<br/><input id="btn_search_cat" type="button" value="Search">'; ?> <script type="text/javascript"> require(['jquery'],function($){ $(document).ready(function(){ let collection = $.parseJSON('<?php echo $collections; ?>'); //localStorage.setItem('collection-items', JSON.stringify(collection)); console.log(collection); //console.log(localStorage.getItem('collection-items')); $('#master_cats').on('change', function(e){ let c = $(this).val(); //console.log(c); $('#child_cats').children('option:not(:first)').remove(); if(c){ let child = collection.find(x=>x.id == c).children; if(child){ //console.log(child); child.map(obj=>{ $('#child_cats').append('<option value="'+obj.id+'">'+obj.name+'</option>'); }); } } }); $('#btn_search_cat').on('click', function(e){ let master_id = $('#master_cats').val(); if(master_id){ let url_search = ""; let master = collection.find(x=>x.id == master_id); let child_id = $('#child_cats').val(); if(child_id){ let child = master.children; //alert(child.find(x=>x.id == child_id).url); url_search = child.find(x=>x.id == child_id).url; }else{ //alert(master.url); url_search = master.url; } $(location).attr('href', url_search); }else{ alert('Select the Category first!'); } }); }); }); </script> |