Magento – Magento 2 – Add new attribute (delivery_time) to recently viewed widget

additional-informationknockoutmagento2recently-viewed

What files need to be changed to display additional attributes in recently view products widget?

In the widget settings there is only name, price, image and learn_more available.

For the product attribute name i've spotted the file

vendor/magento/module-catalog/view/frontend/ui_component/widget_recently_viewed.xml:

<column name="name" component="Magento_Catalog/js/product/name" sortOrder="1" displayArea="details-area">
    <settings>
        <label translate="true">Name</label>
        <bodyTmpl>Magento_Catalog/product/name</bodyTmpl>
    </settings>
</column>

and vendor/magento/module-catalog/view/base/web/template/product/name.html:

<strong if="isAllowed()"
        class="product-item-name">
    <a attr="href: $row().url" html="$col.getLabel($row())"/>
</strong>

I'm really confused about the $col.getLabel($row()), is there any documentation out there that covers this functionality?

What files needs to be changed for adding delivery_time or sku to the widget and where to put them?

Any help would appreciated

Best Answer

I managed to figure this out (albeit using reviews as a source of inspiration). This has been tested and is working on Magento 2.3.3

Namespace/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorComposite">
    <arguments>
        <argument name="productProviders" xsi:type="array">
            <item name="sku" xsi:type="object">\Namespace\Module\Ui\DataProvider\Product\Listing\Collector\Sku</item>
        </argument>
    </arguments>
</type>
</config>

Namespace/Module/etc/extension_attributes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Catalog\Api\Data\ProductRenderInterface">
        <attribute code="sku" type="string"/>
    </extension_attributes>
</config>

Namespace/Module/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="catalog_recently_viewed">
        <parameters>
            <parameter name="show_attributes" xsi:type="multiselect" required="true" visible="true">
                <options>
                    <option name="sku" value="sku">
                        <label translate="true">SKU</label>
                    </option>
                </options>
            </parameter>
        </parameters>
    </widget>
</widgets>

Namespace/Module/Ui/DataProvider/Product/Listing/Collector/Sku.php

<?php
namespace Namespace\Module\Ui\DataProvider\Product\Listing\Collector;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductRenderExtensionFactory;
use Magento\Catalog\Api\Data\ProductRenderInterface;
use Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorInterface;

class Sku implements ProductRenderCollectorInterface
{
    /** SKU html key */
    const KEY = "sku";

    /**
     * @var ProductRenderExtensionFactory
     */
    private $productRenderExtensionFactory;

    /**
     * Sku constructor.
     * @param ProductRenderExtensionFactory $productRenderExtensionFactory
     */
    public function __construct(
        ProductRenderExtensionFactory $productRenderExtensionFactory
    ) {
        $this->productRenderExtensionFactory = $productRenderExtensionFactory;
    }

    /**
     * @inheritdoc
     */
    public function collect(ProductInterface $product, ProductRenderInterface $productRender)
    {
        $extensionAttributes = $productRender->getExtensionAttributes();

        if (!$extensionAttributes) {
            $extensionAttributes = $this->productRenderExtensionFactory->create();
        }

        if($product->getSku())
        {
            $extensionAttributes
                ->setSku($product->getSku());
        }

        $productRender->setExtensionAttributes($extensionAttributes);
    }
}

Namespace/Module/view/frontend/ui_component/widget_recently_viewed.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="widget_columns">
        <column name="sku" component="Namespace_Module/js/product/sku" displayArea="description-area">
            <settings>
                <label translate="true">SKU</label>
                <bodyTmpl>Namespace_Module/product/sku</bodyTmpl>
            </settings>
        </column>
    </columns>
</listing>

Namespace/Module/view/frontend/web/js/product/sku.js

define([
    'Magento_Ui/js/grid/columns/column',
    'Magento_Catalog/js/product/list/column-status-validator'
], function (Column, columnStatusValidator) {
    'use strict';

    return Column.extend({

        /**
         * @param row
         * @returns {boolean}
         */
        hasValue: function (row) {
            return "sku" in row['extension_attributes'];
        },

        /**
         * @param row
         * @returns {*}
         */
        getValue: function (row) {
            return row['extension_attributes']['sku'];
        },

        /**
         * @param row
         * @returns {*|boolean}
         */
        isAllowed: function (row) {
            return (columnStatusValidator.isValid(this.source(), 'sku', 'show_attributes') && this.hasValue(row) );
        }

    });
});

Namespace/Module/view/frontend/web/template/product/sku.html

<strong if="isAllowed($row())"
   class="product sku">
    <span class="label" text="label" />
    <span class="value" text="getValue($row())" />
</strong>

One thing you'll need to bear in mind is that recently viewed stores data in browser storage when an item is viewed - it won't update the data that is already there with your new attributes. So when testing please remember to clear your browser storage! (Speaking from experience, this tripped me up for quite a while)


EDIT: Show how to render both label and value in the .html file

Related Topic