Magento 2 – How to Render Widgets in Product and Category Descriptions

magento2template-directivewidgetwidgets

In Magento 2 we can add widgets to CMS pages and CMS blocks with a directive like this (assuming we created this custom widget with a module before):

{{widget type="Vendor\Module\Block\Widget\CustomWidget" some_addtribute="some-value"}}

When we add the same widget code in product or category description it is not rendered. So the output is the text string from above.

How can we extend Magento 2 in a way that it will render widgets in product or category descriptions as well?

Best Answer

Instead of instantiating the object manager and filterprovider etc. in your template, consider this:

In your block class (Vendor\Module\Block\Widget\CustomWidget) include the dependencies in your constructor:

/**
 * Example constructor.
 * @param \Magento\Cms\Model\Template\FilterProvider $filterProvider
 * @param \Magento\Catalog\Helper\Output $catalogOutputHelper
 * @param \Magento\Framework\View\Element\Template $context
 * @param array $data
 */
public function __construct(
    \Magento\Cms\Model\Template\FilterProvider $filterProvider,
    \Magento\Catalog\Helper\Output $catalogOutputHelper,
    \Magento\Framework\View\Element\Template $context,
    array $data = []
) {
    $this->filterProvider = $filterProvider;
    $this->catalogOutputHelper = $catalogOutputHelper;
    \Magento\Framework\View\Element\Template::__construct($context, $data);
}

Now in your block class add a method to filter the input:

/**
 * @param string $description
 * @return string
 */
public function getFilteredContent(string $description)
{
    return $this->filterProvider
        ->getBlockFilter()
        ->filter(
            $this->catalogOutputHelper->categoryAttribute(
                $this->getCurrentCategory(),
                $description,
                'description'
            )
        );
}

I assume that getCurrentCategory() is a method you've already created.

Now in your template, you can simply do:

echo $block->getFilteredDescription($_description);

So now your template is neat and tidy and all dependencies and business logic are separated to you block class, as it should.