1

I'm developing a module with a widget. I make my own widget.xml following some differents guide in the net.

But, I've configured the widget from the back-office and I can't retrieve the widget data. It always returns NULL and all the data seem to not exists. See the 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="tata_toto_widget" class="TATA\TOTO\Block\Widget\Reco" is_email_compatible="true">
        <label translate="true">Tata Toto</label>
        <description>Tata Toto widget.</description>
        <parameters>
            <parameter name="label" xsi:type="text" required="false" visible="true">
                <label translate="true">Label</label>
                <description translate="true">
                    Define the title appearing above recommendations in the template.
                </description>
            </parameter>
            <parameter name="zone_id" xsi:type="text" required="true" visible="true">
                <label translate="true">Zone Id</label>
            </parameter>
            <parameter name="number_of_recommendation" xsi:type="text" required="true" visible="true">
                <label translate="true">Number of recommendations</label>
                <description translate="true">Define how many items will be shown on the template.</description>
                <value>5</value>
            </parameter>
            <parameter name="page_type" xsi:type="select" required="true" visible="true"
                       source_model="TATA\TOTO\Model\Config\Source\PageType">
                <label translate="true">Page type</label>
            </parameter>
            <parameter name="force_product" xsi:type="select" required="true" visible="true"
                       source_model="Magento\Config\Model\Config\Source\Yesno">
                <label translate="true">Force product recommendation</label>
            </parameter>
            <parameter name="attribute_name_sort" xsi:type="text" required="false" visible="true">
                <label translate="true">Attribute name to sort</label>
                <depends>
                    <parameter name="page_type" value="Sort" />
                </depends>
            </parameter>
            <parameter name="order" xsi:type="select" required="false" visible="true"
                       source_model="TATA\TOTO\Model\Config\Source\SortOrder">
                <label translate="true">Order to sort</label>
                <depends>
                    <parameter name="page_type" value="Sort" />
                </depends>
            </parameter>
            <parameter name="group_by" xsi:type="text" required="false" visible="true">
                <label translate="true">Group by attribute</label>
                <depends>
                    <parameter name="page_type" value="Catalog" />
                </depends>
            </parameter>
            <parameter name="template" xsi:type="select" required="true" visible="true">
                <label translate="true">Template</label>
                <description translate="true">
                    The template on which the reco will be done.
                </description>
                <options>
                    <option name="horizontal" value="TOTO_TATA::widget/horizontal.phtml" selected="true">
                        <label translate="true">Horizontal Grid Template</label>
                    </option>
                    <option name="vertical" value="TOTO_TATA::widget/vertical.phtml">
                        <label translate="true">Vertical Grid Template</label>
                    </option>
                </options>
            </parameter>
        </parameters>
    </widget>
</widgets>

So I linked the widget to the Block TATA\TOTO\Block\Widget\Reco, here the block's code:

<?php

namespace TATA\TOTO\Block\Widget;

use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
use Magento\Framework\View\Element\Template\Context;
use TATA\TOTO\Model\Api\RecoApi;
use Magento\Framework\Registry;

/**
 * Class Reco
 *
 * @package TATA\TOTO
 * @author Tata Developper Team <tech@tata.com>
 */
class Reco extends AbstractRecoBlock
{
    /* @var ProductCollectionFactory */
    protected $_productCollectionFactory;

    /* @var ProductCollection $_productCollection */
    protected $_productCollection = null;

    /* @var array $options */
    public $options = array();

    /**
     * Reco constructor.
     *
     * @param Context $context
     * @param Registry $registry
     * @param ProductCollectionFactory $productCollectionFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        Registry $registry,
        ProductCollectionFactory $productCollectionFactory,
        array $data = [])
    {
        $this->_productCollectionFactory = $productCollectionFactory;

        parent::__construct($context, $registry, $data);

        var_dump($this->_data);

        // Initializing options array.
        $this->options['productBiz'] = $this->retrieveActualProducts();
        $this->options['serverUrl'] = $this->getTotoUrl();
        $this->options['tenantId'] = $this->getTenant();
        $this->options['zoneId'] = $this->getZoneId();
        $this->options['pageType'] = $this->getPageType();
        $this->options['forceProduct'] = $this->getForceProduct();
        $this->options['numberOfRecommendation'] = $this->getNumberOfRecommendation();
        $this->options['order'] = $this->getOrder();
        $this->options['groupBy'] = $this->getGroupBy();
        $this->options['attributeNameSort'] = $this->getAttributeNameSort();

        var_dump($this->options); // See the output below
    }
// ...
}

array(10) { ["productBiz"]=> array(1) { [0]=> string(4) "WT09" } ["serverUrl"]=> string(33) "someUrl" ["tenantId"]=> int(157) ["zoneId"]=> NULL ["pageType"]=> NULL ["forceProduct"]=> NULL ["numberOfRecommendation"]=> NULL ["order"]=> NULL ["groupBy"]=> NULL ["attributeNameSort"]=> NULL }

All the NULL values are sets in the widget back-office. And I remove all my getX() functions for the initial "magic" function.

When I var_dump($this->_data); which is the array which must contains the widget data I have nothing.

array(0) { }

AbstractRecoBlock (which is extended from the above given block) is now totaly empty and extends from Magento\Framework\View\Element\Template and implements Magento\Widget\Block\BlockInterface.

Here one of the guide I've following from A to Z: https://gielberkers.com/creating-widgets-in-magento-2/.

Do you have any leads?

Thanks!

2

Ok, I found the error.

It's not possible to reach _data from the constructor (even if you execute the parent before). So you have to create a function wich will initialize your widget options and call it in the template (or _toHtml() I think). So I have the following code in my block and it works:

<?php

namespace TOTO\TATA\Block\Widget;

use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use TOTO\TATA\Model\Api\RecoApi;
use Magento\Framework\Registry;
use Magento\Widget\Block\BlockInterface;


/**
 * Class Reco
 *
 * @package TOTO\TATA
 * @author TOTO Developper Team <tech@toto.com>
 */
class Reco extends Template implements BlockInterface
{
    /* @var ProductCollectionFactory $_productCollectionFactory */
    protected $_productCollectionFactory;

    /* @var ProductCollection $_productCollection */
    protected $_productCollection = null;

    /* @var Registry $registry */
    protected $_registry;

    /* @var array $options */
    public $options = array();

    /**
     * Reco constructor.
     *
     * @param Context $context
     * @param Registry $registry
     * @param ProductCollectionFactory $productCollectionFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        Registry $registry,
        ProductCollectionFactory $productCollectionFactory,
        array $data = [])
    {
        parent::__construct($context, $data);

        $this->_productCollectionFactory = $productCollectionFactory;
        $this->_registry = $registry;
    }

    public function initializeOptions()
    {
        $this->options['zoneId'] = $this->getZoneId();
        $this->options['pageType'] = $this->getPageType();
        $this->options['forceProduct'] = $this->getForceProduct();
        $this->options['numberOfRecommendation'] = $this->getNumberOfRecommendation();
        $this->options['order'] = $this->getSortOrder();
        $this->options['groupBy'] = $this->getGroupBy();
        $this->options['attributeNameSort'] = $this->getAttributeNameSort();
    }
    // Code...
}

And here my template:

<?php

$this->initializeOptions();
var_dump($this->options);

It works well. I extends again my block from an abstract one with all getX() functions like this:

/**
 * Gets the "Label" data safely.
 *
 * @return string
 */
protected function getLabel()
{
    if (!$this->hasData('label')) {
        $this->setData('label', self::DEFAULT_LABEL);
    }
    return (string)$this->getData('label');
}

Hope this will help some people :)

  • 1
    This makes no sense, but it worked for me too. Thanks man – bottens May 26 '17 at 11:23

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.