Category and sub category image widget
-
22-01-2021 - |
Question
I tried to create category and subcategory image widget.I got first level of categories with category images.
app/code/Customcategory/CatewithimgWidget/Block/Widget CatewithimgWidget.php
class CatewithimgWidget extends
\Magento\Framework\View\Element\Template implements
\Magento\Widget\Block\BlockInterface
{
protected $_template = 'widget/categorywidget.phtml';
/**
* Default value for products count that will be shown
*/
protected $_categoryHelper;
protected $categoryFlatConfig;
protected $topMenu;
protected $_categoryFactory;
protected $mainTitle;
protected $tagLine;
/**
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Catalog\Helper\Category $categoryHelper
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Catalog\Helper\Category $categoryHelper,
\Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState,
\Magento\Catalog\Model\CategoryFactory $categoryFactory,
\Magento\Theme\Block\Html\Topmenu $topMenu
) {
$this->_categoryHelper = $categoryHelper;
$this->categoryFlatConfig = $categoryFlatState;
$this->topMenu = $topMenu;
$this->_categoryFactory = $categoryFactory;
parent::__construct($context);
}
/**
* Return categories helper
*/
public function getCategoryHelper()
{
return $this->_categoryHelper;
}
public function getCategorymodel($id)
{
$_category = $this->_categoryFactory->create();
$_category->load($id);
return $_category;
}
/**
* Retrieve current store categories
*
* @param bool|string $sorted
* @param bool $asCollection
* @param bool $toLoad
* @return \Magento\Framework\Data\Tree\Node\Collection|\Magento\Catalog\Model\Resource\Category\Collection|array
*/
/**
* Retrieve collection of selected categories
*/
public function getCategoryCollection()
{
$rootCat = $this->getData('parentcat');
$category = $this->_categoryFactory->create();
$collection = $category
->getCollection()
->addAttributeToSelect('image')
->addIdFilter($rootCat);
return $collection;
}
public function getMainTitle()
{
$mainTitle = $this->getData('blocktitle');
return $mainTitle;
}
}
app/code/Customcategory/CatewithimgWidget/etc module.xml
<?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="Customcategory_CatewithimgWidget" setup_version="1.0.0">
</module>
app/code/Customcategory/CatewithimgWidget/etc widget.xml
<?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="Customcategory_catewithimgwidget"
class="Customcategory\CatewithimgWidget\Block\Widget
\CatewithimgWidget">
<label translate="true">Category List with image Widget</label>
<description>Store Default 1st level Category List
Widget</description>
<parameters>
<parameter name="blocktitle" xsi:type="text" visible="true"
required="true" sort_order="1">
<label translate="true">Block Title</label>
</parameter>
<parameter name="tagline" xsi:type="text" visible="true"
required="true" sort_order="2">
<label translate="true">class</label>
</parameter>
<parameter name="parentcat" xsi:type="multiselect"
visible="true" sort_order="3"
source_model="Customcategory\CatewithimgWidget\Model\Config\Source
\Categorylist">
<label translate="true">Select Categories</label>
<description translate="true">Category must have image
uploaded</description>
</parameter>
</parameters>
</widget>
</widgets>
app/code/Customcategory/CatewithimgWidget/Model/Config/Source/Categorylist.php
<?php
namespace Customcategory\CatewithimgWidget\Model\Config\Source;
use Magento\Framework\Option\ArrayInterface;
use Magento\Catalog\Helper\Category;
class Categorylist implements ArrayInterface
{
protected $_categoryHelper;
public function __construct(\Magento\Catalog\Helper\Category
$catalogCategory)
{
$this->_categoryHelper = $catalogCategory;
}
/*
* Return categories helper
*/
public function getStoreCategories($sorted = false, $asCollection = false, $toLoad = true)
{
return $this->_categoryHelper->getStoreCategories($sorted , $asCollection, $toLoad);
}
/*
* Option getter
* @return array
*/
public function toOptionArray()
{
$arr = $this->toArray();
$ret = [];
foreach ($arr as $key => $value)
{
$ret[] = [
'value' => $key,
'label' => $value
];
}
return $ret;
}
/*
* Get options in "key-value" format
* @return array
*/
public function toArray()
{
$categories = $this->getStoreCategories(true,false,true);
$catagoryList = array();
foreach ($categories as $category){
$catagoryList[$category->getEntityId()] = __($category->getName());
}
return $catagoryList;
}
}
?>
app/code/Customcategory/CatewithimgWidget/view/frontend/layout/default.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="Customcategory_CatewithimgWidget::css/widget.css" />
</head>
app/code/Customcategory/CatewithimgWidget/view/frontend/templates/widget/categorywidget.phtml
<?php
$categories = $this->getCategoryCollection();
$categoryHelper = $this->getCategoryHelper();
?>
<div class="widget block block-static-block cwiw" id="catewithimg">
<div class="block-content">
<div class="content-heading">
<h2 class="title"><?php echo $this->getMainTitle(); ?></h2>
<div class="row">
<?php
foreach($categories as $category):
$cat = $this->getCategorymodel($category->getId());
$image = $cat->getImageUrl();
?>
<?php if($image != null): ?>
<div class="col-md-4">
<a class="category_name" href="<?php echo $cat-
>getUrl(); ?>">
<img src="<?php echo $image; ?>" class="img-responsive category_image" alt="<?php echo $cat->getName(); ?>" />
<h3><span><?php echo $cat->getName(); ?></span></h3>
</a>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
</div>
app/code/Customcategory/CatewithimgWidget/view/frontend/web/css/widget.css
.cwiw{
width: 100%;
clear: both;
float: none;
text-align: center;
}
.cwiw .row{
margin-bottom: 20px;
margin-right: -15px;
margin-left: -15px;
}
.cwiw .row:before,
.cwiw .row:after{
display: table;
content: " ";
}
.cwiw .row .col-md-4{
width: 33.33333333%;
float: left;
}
.cwiw a:hover{
text-decoration: none;
}
the widget looks like
how to get a category tree instead of select category
Solution
You need to replace your widget.xml with below code:
<?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="Customcategory_catewithimgwidget" class="Customcategory\CatewithimgWidget\Block\Widget\CatewithimgWidget">
<label translate="true">Category List with image Widget</label>
<description>Store Default 1st level Category List Widget</description>
<parameters>
<parameter name="blocktitle" xsi:type="text" visible="true" required="true" sort_order="1">
<label translate="true">Block Title</label>
</parameter>
<parameter name="tagline" xsi:type="text" visible="true" required="true" sort_order="2">
<label translate="true">class</label>
</parameter>
<parameter name="parentcat" xsi:type="block" visible="true" required="true" sort_order="10">
<label translate="true">Categories</label>
<description translate="true">Category must have image uploaded</description>
<block class="Customcategory\CatewithimgWidget\Block\Adminhtml\Chooser" />
</parameter>
</parameters>
</widget>
</widgets>
And need to create one more Block Class like below: Under
app/code/Customcategory/CatewithimgWidget/Block/Adminhtml/Chooser.php
<?php
namespace Customcategory\CatewithimgWidget\Block\Adminhtml;
class Chooser extends \Magento\Backend\Block\Template {
protected $_elementFactory;
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Data\Form\Element\Factory $elementFactory, array $data = []
) {
$this->_elementFactory = $elementFactory;
parent::__construct($context, $data);
}
public function prepareElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element) {
$htmlId = $element->getId();
$data = $element->getData();
$data['after_element_js'] = $this->_afterElementJs($element);
$data['after_element_html'] = $this->_afterElementHtml($element);
$data['readonly'] = 'readonly';
$htmlItem = $this->_elementFactory->create('text', ['data' => $data]);
$htmlItem
->setId("{$htmlId}")
->setForm($element->getForm())
->addClass('required-entry')
->addClass('entities');
$return = <<<HTML
<div id="{$htmlId}-container" class="chooser_container">{$htmlItem->getElementHtml()}</div>
HTML;
$element->setData('after_element_html', $return);
return $element;
}
protected function _afterElementHtml($element)
{
$htmlId = $element->getId();
$return = <<<HTML
<a href="javascript:void(0)" onclick="MultiCategoryChooser.displayChooser('{$htmlId}-container')" class="widget-option-chooser" title="{__('Open Chooser')}">
<img src="{$this->getViewFileUrl('images/rule_chooser_trigger.gif')}" alt="{__('Open Chooser')}" />
</a>
<a href="javascript:void(0)" onclick="MultiCategoryChooser.hideChooser('{$htmlId}-container')" title="{__('Apply')}">
<img src="{$this->getViewFileUrl('images/rule_component_apply.gif')}" alt="{__('Apply')}">
</a>
<div class="chooser"></div>
HTML;
return $return;
}
protected function _afterElementJs($element)
{
$chooserUrl = $this->getUrl('adminhtml/widget_instance/categories', []);
$htmlId = $element->getId();
$return = <<<HTML
<script>
require([
'jquery',
'Magento_Ui/js/modal/alert',
"prototype"
], function (jQuery, alert) {
var MultiCategoryChooser = {
displayChooser : function(chooser) {
chooser = $(chooser).down('div.chooser');
entities = chooser.up('div.chooser_container').down('input[type="text"].entities').value;
postParameters = {selected: entities};
url = '{$chooserUrl}';
if (chooser && url) {
if (chooser.innerHTML == '') {
new Ajax.Request(url, {
method : 'post',
parameters : postParameters,
onSuccess : function(transport) {
try {
if (transport.responseText) {
Element.insert(chooser, transport.responseText);
chooser.removeClassName('no-display');
chooser.show();
}
} catch (e) {
alert({
content: 'Error occurs during loading chooser.'
});
}
}
});
} else {
chooser.removeClassName('no-display');
chooser.show();
}
}
},
hideChooser : function(chooser) {
chooser = $(chooser).down('div.chooser');
if (chooser) {
chooser.addClassName('no-display');
chooser.hide();
}
},
checkCategory : function(event) {
node = event.memo.node;
container = event.target.up('div.chooser_container');
value = container.down('input[type="text"].entities').value.strip();
if (node.attributes.checked) {
if (value) ids = value.split(',');
else ids = [];
if (-1 == ids.indexOf(node.id)) {
ids.push(node.id);
container.down('input[type="text"].entities').value = ids.join(',');
}
} else {
ids = value.split(',');
while (-1 != ids.indexOf(node.id)) {
ids.splice(ids.indexOf(node.id), 1);
container.down('input[type="text"].entities').value = ids.join(',');
}
}
}
}
window.MultiCategoryChooser = MultiCategoryChooser;
jQuery(function() {
var container = $('{$htmlId}-container');
if (container) {
container.up(0).down('.control-value').hide();
}
Event.observe(document, 'node:changed', function(event){
MultiCategoryChooser.checkCategory(event);
});
Event.observe(document, 'category:beforeLoad', function(event) {
container = event.target.up('div.chooser_container');
value = container.down('input[type="text"].entities').value.strip();
event.memo.treeLoader.baseParams.selected = value;
});
});
});
</script>
HTML;
return $return;
}
}
Thats it. Run di compile and other necessary commands.
Hope this helps!