Custom Widget

By | December 9th 2018 02:05:24 AM | viewed 241 times

How to make custom widget for CatImageBanner in Magento2

Magento 2 is a Model View ViewModel (MVVM) system. While being closely related to its sibling Model View Controller (MVC), an MVVM architecture provides a more robust separation between the Model and the View layers. Below is an explanation of each of the layers of a MVVM system:

  • The Model holds the business logic of the application, and depends on an associated class—the ResourceModel—for database access. Models rely on service contracts to expose their functionality to the other layers of the application.
  • The View is the structure and layout of what a user sees on a screen - the actual HTML. This is achieved in the PHTML files distributed with modules. PHTML files are associated to each ViewModel in the Layout XML files, which would be referred to as binders in the MVVM dialect. The layout files might also assign JavaScript files to be used in the final page.
  • The ViewModel interacts with the Model layer, exposing only the necessary information to the View layer. In Magento 2, this is handled by the module’s Block classes. Note that this was usually part of the Controller role of an MVC system. On MVVM, the controller is only responsible for handling the user flow, meaning that it receives requests and either tells the system to render a view or to redirect the user to another route.

A Magento 2 module can in turn define external dependencies by using Composer, PHP’s dependency manager. Magento 2 core modules depend on the Zend Framework, Symfony as well as other third-party libraries.It is also interesting to notice that, in practice, all of Magento 2’s inner workings live inside a module. for example, Magento_Checkout responsible for the checkout process, and Magento_Catalog responsible for the handling of products and categories.

Below is the structure of Magento_Cms, a Magento 2 core module responsible for handling the creation of pages and static blocks.

Each folder of a Module holds one part of the architecture, as follows:

  • Api: Service contracts, defining service interfaces and data interfaces
  • Block: The ViewModels of our MVVM architecture
  • Controller: Controllers, responsible for handling the user’s flow while interacting with the system
  • etc: Configuration XML files—The module defines itself and its parts (routes, models, blocks, observers, and cron jobs) within this folder. The etc files can also be used by non-core modules to override the functionality of core modules.
  • Helper: Helper classes that hold code used in more than one application layer. For example, in the Cms module, helper classes are responsible for preparing HTML for presentation to the browser.
  • i18n: Holds internationalization CSV files, used for translation
  • Model: For Models and ResourceModels
  • Observer: Holds Observers, or Models which are “observing” system events. Usually, when such an event is fired, the observer instantiates a Model to handle the necessary business logic for such an event.
  • Setup: Migration classes, responsible for schema and data creation
  • Test: Unit tests
  • Ui: UI elements such as grids and forms used in the admin application
  • view: Layout (XML) files and template (PHTML) files for the front-end and admin application

Before we move on to implementation, let’s take a closer look at the standard range of widgets supported in Magento 2

  • Recently Compared Products
  • Orders and Returns
  • Catalog Products List
  • Catalog Product Link
  • Catalog Category Link
  • Custom Block Widget

Creating Our First Magento 2 CatImageBanner Widget

Registering Our Module

Now we will register our module with Magento. Go ahead and create a file registration.php in the location : app/code/UKM/CatImageBanner/ with the following code where UKM is the namespace and Post is the Module name

	<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'UKM_CatImageBanner',
    __DIR__
);

  

Create a file composer.json in the location : app/code/UKM/CatImageBanner/ with the following code

   {
    "name": "UKM/CatImageBanner",
    "description": "UKM Category List Widget with images",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0"
    },
    "type": "magento2-module",
    "version": "1.0.0",
    "license": [
        "Commercial"
    ],
    "autoload": {
        "files": [ "registration.php" ],
        "psr-4": {
            "UKM\\CatImageBanner\\": ""
        }
    }
}
  

Create a file module.xml in the location : app/code/UKM/CatImageBanner/etc/ with the following code

	<?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="UKM_CatImageBanner" setup_version="1.0.0">
	    </module>
	</config>
  

Create a file widget.xml in the location : app/code/UKM/CatImageBanner/etc/ with the following 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="ukm_catimagebanner" class="UKM\CatImageBanner\Block\Widget\CatewithimgWidget">
				<label translate="true">UKM Category List with image Widget>
				<description>Store Default 1st level Category List Widget>
				<parameters>
		            <parameter name="blocktitle" xsi:type="text"  visible="true" required="true" sort_order="1">
		                <label translate="true">Block Title>
		            </parameter>
		            <parameter name="tagline" xsi:type="text"  visible="true" required="true" sort_order="2">
		                <label translate="true">Tag Line>
		            </parameter>
					<parameter name="parentcat"  xsi:type="multiselect"  visible="true" sort_order="3" source_model="UKM\CatImageBanner\Model\Config\Source\Categorylist">
		                <label translate="true">Select Categories (Any three) </label>
		                <description translate="true">Category must have image uploaded</description>
		            </parameter>
				</parameters>
			</widget>
		</widgets>
  

Now we run the following command to upgrade database info

    projectname>php bin/magento setup:upgrade
	projectname>php bin/magento cache:flush
  

Now we check module status by the command

    projectname>php bin/magento module:status
  

If the module is shown in the module list and is disable, then run the following command

    projectname>php bin/magento module:enable UKM_CatImageBanner
  

Create Model to face data:

Now create a file Categorylist.php to implementation the data interface in the location: app/code/UKM/CatImageBanner/Model/Config/Source/ with the following codes

  
  <?php
  
  
namespace UKM\CatImageBanner\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;
    }

}
?>

  

Define Block:

Create a file CatewithimgWidget.php in the location: app/code/UKM/CatImageBanner/Block/Widget/ with the following code

  <?php

namespace UKM\CatImageBanner\Block\Widget;

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;
    }
    /**
     * Retrieve tag line for widget
    */
    public function getTagLine()
    {
        $tagLine = $this->getData('tagline');
        return $tagLine;
    }
    /**
     * Retrieve main title for widget
    */
    public function getMainTitle()
    {
        $mainTitle = $this->getData('blocktitle');
        return $mainTitle;
    }
}

  

Define View:

Create a file default.xml in the location: app/code/UKM/CatImageBanner/view/frontend/layout with the following code

  <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <css src="UKM_CatImageBanner::css/widget.css" />
    </head>
   </page>

  

Create a file categorywidget.phtml in the location: app/code/UKM/CatImageBanner/view/frontend/templates/widget/ with the following code

    <?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>
		            <p class="info"><?php echo $this->getTagLine(); ?></p>
		        </div>
		        <div class="row" style="clear:both;">
		        <?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="getUrl(); ?>">
		                       <img src<?php echo $image; ?>" class="img-responsive category_image" alt="<?php echo $cat->getName(); ?>" />
		                        <h3><?php echo $cat->getName(); ?></h3>
		                    </a>
		                </div>
		            <?php endif; ?>
		        <?php endforeach; ?>
		        </div>
		    </div>
			<div style="clear:both;"></div>
		</div>

   

Create a file widget.css in the location: app/code/UKM/CatImageBanner/view/frontend/web/css/ with the following code

		.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;
		}

   

Run the following command or manually flush cache from admiin panel

projectname>php bin/magento setup:upgrade
projectname>php bin/magento cache:flush

Login to admin panel and assign widget where you want to view category image list

bONEandALL