Remove current product from Recently Viewed Products on the product view page
-
09-01-2021 - |
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.
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.