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 enter image description here how to get a category tree instead of select category

Was it helpful?

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top