0

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+ (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.

2

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;
            }
        });
    }
});
  • I'll test this later on today, but it seems to be the right solution. Cheers! – Lez Oct 16 '18 at 11:13
  • Unfortunately I was not able to get this to work. I keep getting this._super is not a function JS error. So you probably didn't mention all the changes that you made. – Lez Oct 16 '18 at 19:24
  • filterIds extends the original filterIds function. I've updated my answer with full provider.js content – Roman S. Oct 17 '18 at 8:03
  • This fixed the JS error, but I'm still having trouble getting it to work. I don't get the currentProductId property in this.data. So I presume something is wrong with the php part of the code. What is UiDataProvider in your afterGetData method? I used \Magento\Catalog\Ui\DataProvider\Product\Listing\DataProvider. Also for registry, I used a construct with \Magento\Framework\Registry $registry is this correct? Is anything else missing maybe? – Lez Oct 17 '18 at 21:01
  • 1
    Cool! And thank you for the idea where to start digging :) – Roman S. Oct 18 '18 at 19:21
1

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.

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.