Question

Basically the same question was asked here: Magento 2 shows current product as recently viewed product but the answer there doesn't apply for Magento 2.2 versions (or which ever version introduced the recently viewed widget as a ui component).

So I'm wondering if anyone has an idea how to remove the current product (which the customer is viewing on the product view page) from the recently viewed widget which is placed on the product view page?

I've tracked the functionality to Magento_Catalog/ui_component/widget_recently_viewed.xml and to the template file Magento_Catalog/web/template/product/list/listing.html which calls the filteredRows function from Magento_Catalog/web/js/product/list/listing.js.

But I'm not sure how to exclude the current product from the data source, so any help would be appreciated.

EDIT This seems to be solved by default in Magento 2.3.3+ versions.

Was it helpful?

Solution

Based on Lez answer: in my case, some products don't have prices. And I couldn't rely on finding the current product ID in DOM.

Instead, I've created a plugin for Magento\Catalog\Ui\DataProvider\Product\Listing\DataProvider. 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\Listing\DataProvider">
        <plugin name="ui_listing_data_provider"
            type="Vendor\Catalog\Plugin\Ui\DataProvider\Product\Listing\DataProvider"/>
    </type>
</config>

And add there a current product ID from Magento Registry:

DataProvider.php:

class DataProvider
{
    protected $registry;

    /**
     * DataProvider constructor.
     * 
     * @param \Magento\Framework\Registry $registry
     */
    public function __construct(
        \Magento\Framework\Registry $registry
    ) {
        $this->registry = $registry;
    }

    /**
     * Adds current product ID for product listing ui component
     *
     * @param \Magento\Catalog\Ui\DataProvider\Product\Listing\DataProvider $subject
     * @param array $result
     *
     * @return array
     */
    public function afterGetData(
        \Magento\Catalog\Ui\DataProvider\Product\Listing\DataProvider $subject,
        $result
    ) {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $this->registry->registry('current_product');

        if (!empty($product) && $product instanceof Product) {
            $result['currentProductId'] = $product->getId();
        }

        return $result;
    }
}

Let's say to Magento we're going to extend provider.js:

var config = {
    config: {
        mixins: {
            'Magento_Catalog/js/product/provider': {
                'Vendor_Catalog/js/product/provider': true
            }
        }
    }
};

And then, just exclude the product with specified ID:

define([], function () {
'use strict';

    return function (Provider) {
        return Provider.extend({
            filterIds: function () {
                let ids = this._super();

                if (this.data.hasOwnProperty('currentProductId')) {
                    // Current product ID is set - we're on the product page
                    if (ids.hasOwnProperty(this.data.currentProductId)) {
                        // Current product ID exists in the list - exclude it
                        delete ids[this.data.currentProductId];
                    }
                }

                return ids;
            }
        });
    }
});

OTHER TIPS

I came up with this solution for Mage 2.2+ versions.

Override the filterIds function in Magento_Catalog/web/js/product/provider.js like this:

filterIds: function (ids) {
    var _ids = {},
    currentTime = new Date().getTime() / 1000;

    _.each(ids, function (id) {
        if (currentTime - id['added_at'] < ~~this.idsStorage.lifetime) {
            // Verify that the customer is on the product view page by looking for the data-product-id attribute in the product-info-main container.
            var current_product = $('.product-info-main .price-box').attr('data-product-id');
            if (current_product != '') {
                if (!(id['product_id'] == current_product)) {
                    _ids[id['product_id']] = id;
                }
            } else {
                _ids[id['product_id']] = id;
            }
         }
     }, this);

     return _ids;
 },

Also you have to define jquery in the same file, so you can use it to locate the data-product-id attribute.

define([
    'jquery',
    'underscore',
    'mageUtils',
    'uiElement',
    'Magento_Catalog/js/product/storage/storage-service',
    'Magento_Customer/js/customer-data'
], function ($, _, utils, Element, storage, customerData) {
    'use strict';

This is probably not the best possible solution since some products might not have a price, but it suits my needs just fine.

A more thorough approach would be to get the current product id from backend and then remove it from the array of recently viewed products.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top