2

I've created a Catalog Products Lists widget to use my own template when the items are displayed on the frontend. When I insert the widget via Content > Widgets > 'Add Widget' and set it to be displayed on a specific page (CMS Home Page) and in the Main Content Area – everything works fine... The products are displayed as I'd like them to be.

Now, if I try to add the same widget via Content > Blocks > 'Add New Block' > 'Insert Widget', the following is added to the CMS Block content:

{{widget type="Mike\ProductList\Block\Catalog\Product\ProductList" title="Widget from CMS Block" category_id="26" template="product/list/productlist.phtml"}}

Unfortunately, my widget isn't being displayed in the CMS Block I created. Any ideas why the widget is displaying fine when added via the Widgets page and not being displayed when added to a CMS Block?

UPDATE: In response to Aaron Allen's suggestion

My current etc/widget.xml file looks like the below:

<?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_file.xsd">
<widget 
    id="category_product_list"
    class="Mike\ProductList\Block\Catalog\Product\ProductList"
    is_email_compatible="false"
    placeholder_image="Magento_Widget::placeholder.gif" >
    <label translate="true">Catalog Product List</label>
    <description translate="true">Displays a list of products in a block using my new template</description>
    <parameters>
        <parameter name="title" xsi:type="text" required="true" visible="true">
            <label translate="true">Title (frontend)</label>
        </parameter>
        <parameter name="category_id" xsi:type="block" visible="true" required="true">
            <label translate="true">Category</label>
            <block class="Mike\ProductList\Block\Adminhtml\Catalog\Category\Widget\Chooser">
                <data>
                    <item name="button" xsi:type="array">
                        <item name="open" xsi:type="string">Select Category...</item>
                    </item>
                </data>
            </block>
        </parameter>          
        <parameter name="template" xsi:type="select" required="true" visible="true">
            <label translate="true">Template</label>
            <options>
                <option name="default" value="product/list/mikeProductList.phtml" selected="true">
                    <label translate="true">Product  Template</label>
                </option>
            </options>
        </parameter>
    </parameters>      
</widget>

As you can see, this is telling my widget to use Mike\ProductList\Block\Catalog\Product\ProductList as my class.

<?php

namespace Mike\ProductList\Block\Catalog\Product;

use Magento\Catalog\Block\Product\ListProduct;

class ProductList extends ListProduct {

}

How would I tell the widget to extend Template and implement BlockInterface, if I'm already extending Magento\Catalog\Block\Product\ListProduct to pull in the products?

Do I need to create another class (the one you posted) Magento\Widget\Block\BlockInterface and tell the widget somewhere in the XML to use that too somehow?

  • 1
    in my case core widget also behave like this :-) I am also awaiting for the answer magento.stackexchange.com/questions/130626/… – Bilal Usean Aug 12 '16 at 13:26
  • It's really annoying as I'd like to place the widget in a specific cms block! – MikeMason Aug 12 '16 at 13:36
  • What magento 2 version are you using? – André Ferraz Aug 12 '16 at 14:31
  • Wait so you created a widget via Content - Widgets, now the problem is you can't find the newly created widget when you try to insert one in a CMS pages or block? – André Ferraz Aug 12 '16 at 14:48
  • I created a module. It works if I add it to the frontend using the Widgets page and selecting Specific Page (and the display area). It does not work if I add the widget using the Blocks page (it doesn't appear in the CMS block), though, the rest of the content in the CMS block appears. Basically, the widget isn't being pulled into the CMS block. – MikeMason Aug 12 '16 at 14:50
1

Your widget's block class needs to implement the Magento\Widget\Block\BlockInterface interface.

For example:

use Magento\Framework\View\Element\Template;
use Magento\Widget\Block\BlockInterface;

class WidgetBlock extends Template implements BlockInterface 
{

}
  • Aaron, thank you for your response! Your reply makes sense but I'm not sure how to implement it. I've updated my question with some more information. Any help would be great! – MikeMason Aug 13 '16 at 14:02
  • I extended the Template class as an example, the important part is implements BlockInterface. Just add that part along with the use statement to your block class's definition and you should be good to go. – Aaron Allen Aug 13 '16 at 16:22
  • Awesome, I'll give it a go! As I'm implementing the BlockInterface, do I not have to define the addData() and setData() methods in my new class (seeing as they're declared in the interface...)? – MikeMason Aug 13 '16 at 16:38
  • 1
    You shouldn't have to do that in this case. – Aaron Allen Aug 13 '16 at 16:45
  • @MikeMason, I have used the Catalog Products List widget and applied the condition (If Category is --)to display the products on the home page of our website but the products are not listing the position value which we were given for the products on the Specified Category. I have already asked this question [magento.stackexchange.com/questions/241391/… but not received an answer yet, so I'm asking for the better answer. If you you have any idea, please let me know. Your comment will help others like me. – Siva Sep 17 '18 at 13:01
1

Here is the reason:

Your code do not work in case 2 because when insert widget into block. It will be passed to a filter (Magento\Widget\Model\Template\Filter)

# module-widget\Model\Template\Filter
$widget = $this->_layout->createBlock($type, $name, ['data' => $params])
if(!$widget instanceof \Magento\Widget\Block\BlockInterface) {
   return ''; # This is why you get nothing 
}

In case 1 it shows template because when you create a widget and attach to a page. That widget is a block of that page and so no filter happen.

Here is the solution:

Position of ProductList.php file:

enter image description here

Content of Widget in block (Backend):

enter image description here

Code ProductList.php:

# app/code/Cookiecode/WidgetBlock/Block/Widget/ProductList.php
namespace Cookiecode\WidgetBlock\Block\Widget;

use Magento\Catalog\Api\CategoryRepositoryInterface;
use \Magento\Framework\View\Element\Template as Template;

class ProductList extends \Magento\Catalog\Block\Product\ListProduct implements \Magento\Widget\Block\BlockInterface
{
    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
        \Magento\Catalog\Model\Layer\Resolver $layerResolver,
        CategoryRepositoryInterface $categoryRepository,
        \Magento\Framework\Url\Helper\Data $urlHelper,
        array $data = []
    )
    {
        parent::__construct($context, $postDataHelper, $layerResolver, $categoryRepository, $urlHelper, $data);

        $this->setTemplate($data['template']); # widget/default_template.phtml
    }
}

Content of 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_file.xsd">
    <widget
            id="category_product_list"
            class="Cookiecode\WidgetBlock\Block\Widget\ProductList"
            is_email_compatible="false"
            placeholder_image="Magento_Widget::placeholder.gif" >
        <label translate="true">CookieCode::Catalog Product List</label>
        <description translate="true">Displays a list of products in a block using my new template</description>
        <parameters>
            <parameter name="title" xsi:type="text" required="true" visible="true">
                <label translate="true">Title (frontend)</label>
            </parameter>
            <parameter name="category_id" xsi:type="block" visible="true" required="true">
                <label translate="true">Category</label>
                <block class="Magento\Catalog\Block\Adminhtml\Category\Widget\Chooser">
                    <data>
                        <item name="button" xsi:type="array">
                            <item name="open" xsi:type="string">Select Category...</item>
                        </item>
                    </data>
                </block>
            </parameter>
            <parameter name="template" xsi:type="select" required="true" visible="true">
                <label translate="true">Template</label>
                <options>
                    <option name="default" value="widget/default_template.phtml" selected="true">
                        <label translate="true">Product  Template</label>
                    </option>
                </options>
            </parameter>
        </parameters>
    </widget>
</widgets>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.