0

I'm trying to realize the following behaviour (f.e. on the catalog page):

If a logged in user opens the catalog page of my shop I want to change the style of the "add to wishlist" heart icon if the product is already on the users wishlist.

I want to use the customer-data library to prevent using cacheable=false and so disabling the caching for the whole page. I've noticed that Magentos Wishlist module already uses a section source called 'wishlist' so I decided to use this section also for my purpose. I've overwritten the getItemData method from \Magento\Wishlist\CustomerData\Wishlist to be able to add the sku of the wishlist products.

protected function getItemData(Item $wishlistItem)
{
    $product = $wishlistItem->getProduct();
    return [
        // Add the sku of the product to the local storage
        'sku' => $product->getSku(),
        // .. same as in original method
    ];
}

Afterwards I created the following js file to fetch the information from the wishlist section and check if the product with the given sku is part of the wishlist items.

define([
'uiComponent',
'Magento_Customer/js/customer-data'], function (Component, customerData) {
'use strict';

return Component.extend({
    /** @inheritdoc */
    initialize: function () {
        this._super();
        this.isProductInWishlist = function(sku) {
            var wishlist = customerData.get('wishlist');
            var items = wishlist._latestValue.items;

            if (items) {
                for (var i = 0; i < items.length; i++) {
                    if (String(items[i].sku) === String(sku)) {
                        return true;
                    }
                }
            }

            return false;
        };
    },
});
});

So far, everything works fine. My phtml file for the catalog page items calls the above mentioned js file and adds a simple css class to items, which belong to the wishlist.

Now my problem: If the user wants to add a product to his wishlist from the catalog page and clicks the heart icon, the page gets reloaded (because we overwrote \Magento\Wishlist\Controller\Index\Add to keep the user on the same page) but now all previous marked wishlist products are no longer marked as wishlist products. After some debugging I found out that it maybe seems to be a timing problem, because of the following behaviour:

After adding a new product to the wishlist the wishlist section gets invalidated. After the page reload my js file gets executed, before the wishlist section has finished its invalidating. So the wishlist section is empty and it seems as the user has no wishlist products. But in the Applications Tab > Local Storage of the Chrome Developer Tools I can see that the wishlist section reappears after a few more seconds.

Anybody got an idea if it's really a timing problem and how to solve this? Or does this have another reason? Maybe because of our overwritten Add Controller to keep the user at the catalog page after adding a product to the wishlist? The overwritten execute method looks like this

public function execute()
{
    /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
    $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
    if (!$this->formKeyValidator->validate($this->getRequest())) {
        return $resultRedirect->setPath('*/');
    }

    $wishlist = $this->wishlistProvider->getWishlist();
    if (!$wishlist) {
        throw new NotFoundException(__('Page not found.'));
    }

    $session = $this->_customerSession;

    $requestParams = $this->getRequest()->getParams();

    if ($session->getBeforeWishlistRequest()) {
        $requestParams = $session->getBeforeWishlistRequest();
        $session->unsBeforeWishlistRequest();
    }

    $productId = isset($requestParams['product']) ? (int)$requestParams['product'] : null;
    if (!$productId) {
        $resultRedirect->setPath('*/');
        return $resultRedirect;
    }

    try {
        $product = $this->productRepository->getById($productId);
    } catch (NoSuchEntityException $e) {
        $product = null;
    }

    if (!$product || !$product->isVisibleInCatalog()) {
        $this->messageManager->addErrorMessage(__('We can\'t specify a product.'));
        $resultRedirect->setPath('*/');
        return $resultRedirect;
    }

    try {
        $buyRequest = new \Magento\Framework\DataObject($requestParams);

        $result = $wishlist->addNewItem($product, $buyRequest);
        if (is_string($result)) {
            throw new \Magento\Framework\Exception\LocalizedException(__($result));
        }
        if ($wishlist->isObjectNew()) {
            $wishlist->save();
        }
        $this->_eventManager->dispatch(
            'wishlist_add_product',
            ['wishlist' => $wishlist, 'product' => $product, 'item' => $result]
        );

        $referer = $session->getBeforeWishlistUrl();
        if ($referer) {
            $session->setBeforeWishlistUrl(null);
        } else {
            $referer = $this->_redirect->getRefererUrl();
        }

        $this->_objectManager->get(\Magento\Wishlist\Helper\Data::class)->calculate();

        $this->messageManager->addComplexSuccessMessage(
            'addProductSuccessMessage',
            [
                'product_name' => $product->getName(),
                'referer' => $referer
            ]
        );
    } catch (\Magento\Framework\Exception\LocalizedException $e) {
        $this->messageManager->addErrorMessage(
            __('We can\'t add the item to Wish List right now: %1.', $e->getMessage())
        );
    } catch (\Exception $e) {
        $this->messageManager->addExceptionMessage(
            $e,
            __('We can\'t add the item to Wish List right now.')
        );
    }

    $resultRedirect->setPath('*', ['wishlist_id' => $wishlist->getId()]);
    return $resultRedirect;
}
  • In your require-js file why don't you make the wishlist file that gets loaded after a dependancy of your js module? So it will insure that is loaded first. – Chris Anderson Jul 26 '18 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.