Magento Tips & Tricks

Magento 2: Working with Wishlist

Magento 2 wishlist – list of products that a customer can share with anyone. Another purpose is to keep products you want to buy at a later date. By default it has some limitations and theme developer often need to customize it.

  • Following samples was tested on magento 2.3.0
  • You need to update Vendor/Module in filenames and code to correct values
  1. Number of items in wishlist sidebar
  2. “Add to wishlist” without redirecting to wishlist page
  3. Remove “items” text in wishlist top links
  4. Work with wishlist items in javascript

Number of items in Magento 2 wishlist sidebar

By default you can see 3 last added wishlist items in sidebar. This number is hardcoded in Magento\Wishlist\CustomerData\Wishlist class. There is no corresponding option in admin panel. To override it we will use dependency injection functionality.

– add following line in module di.xml to tell magento to use our class instead of standard one.
Filename: Vendor/Module/etc/frontend/di.xml


– create the class. We override only getItems function, which is used to get wishlist items. If you want to limit wishlist collection, you need to use setPageSize function.
Filename: Vendor/Module/CustomerData/Wishlist.php

<?php

namespace Vendor\Module\CustomerData;

class Wishlist extends \Magento\Wishlist\CustomerData\Wishlist
{
	/**
     * Get wishlist items
     *
     * @return array
     */
    protected function getItems()
    {
        $this->view->loadLayout();

		$collection = $this->wishlistHelper->getWishlistItemCollection();

		//show all wishlist items
		$collection->clear()->setInStockFilter(true)->setOrder('added_at');

		//show 5 wishlist items
		//$collection->clear()->setPageSize(5)->setInStockFilter(true)->setOrder('added_at');

		$items = [];
		foreach ($collection as $wishlistItem) {
			$items[] = $this->getItemData($wishlistItem);
		}
		return $items;
	}
}

“Add to wishlist” without redirecting to wishlist page

When you click “Add to Wishlist” button, it redirect you wishlist page. To fix it we need to override Magento\Wishlist\Controller\Index\Add controller.

– add following line in module di.xml to tell magento to use our class instead of standard one.
Filename: Vendor/Module/etc/frontend/di.xml


– create the class. Basically it duplicate original method, only $resultRedirect updated to use referer url
Filename: Vendor/Module/Controller/Index/Add.php

<?php

namespace Vendor\Module\Controller\Index;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\App\Action;
use Magento\Framework\Data\Form\FormKey\Validator;
use Magento\Framework\Exception\NotFoundException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Controller\ResultFactory;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Add extends \Magento\Wishlist\Controller\Index\Add
{
    /**
     * Adding new item
     *
     * @return \Magento\Framework\Controller\Result\Redirect
     * @throws NotFoundException
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     * @SuppressWarnings(PHPMD.UnusedLocalVariable)
     */
    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->setUrl($this->_redirect->getRefererUrl());
        return $resultRedirect;
    }
}

Remove “items” text in wishlist top links

It can be done in several ways.

– you can use translation file. Like app/design/frontend/Magento/luma/i18n/en_US.csv

"%1 items","%1",module,Magento_Wishlist

– you can override createCounter function in Vendor/Module/CustomerData/Wishlist.php

/**
* Create button label based on wishlist item quantity
*
* @param int $count
* @return \Magento\Framework\Phrase|null
*/
protected function createCounter($count)
{
    return $count;
}

– you can update link template ( by default it is view/frontend/templates/link.phtml ) and change

to

Work with wishlist items in javascript

You might want to get wishlist items array in frontend. For example, to mark products that already in customer’s wishlist. It can be done with help of customer-data object. customer-data updated via ajax, so it might not have the wishlist information at the initialization. Luckily customer data use knockout observable functionality, so we can subscribe to data update event.

Sample below use wishlist items array to add “selected” class to wishlist button. You can use it to decorate button.

– create wishlist_items.js
Filename: Vendor/Module/view/frontend/web/js/wishlist_items.js

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

    return Component.extend({
        /** @inheritdoc */
        initialize: function () {
            var _this = this;
			
            this._super();
			
            this.wishlist = customerData.get('wishlist');
            this.wishlist.subscribe(function(newValue) {
                _this.decorateItems();
            });

            _this.decorateItems();
        },
		
        decorateItems: function() {
                var items = this.wishlist().items;
			
                if (typeof items === 'undefined' || !items.length) return;
			
                $('a.action.towishlist').each(function(){
                        var data = $(this).data('post'),
                            i;
	
                        for (i = 0; i < items.length; i++) {
                            if (data.data.product === items[i].product_id) {
                                $(this).addClass('selected');
                            }
                        }
                    });
                }
    });
});

– add initialization code to your wishlist template

<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "wishlistItems": {
                        "component": "Vendor_Module/js/wishlist_items"
                    }
                }
            }
        }
    }
</script>

8 thoughts on “Magento 2: Working with Wishlist

  1. Hello I want to make an Ajax add to wishlist Functionality in Magento 2

    i am trying to use data-action attribute for that
    i searcher in js/add-to-wishlist there are two fuction OnBindSubmit and __Update where action add to wish list is observed and posted to certain url according to paramters i am trying to interupt product on click at add-to-wishlist how can i do this please Guide me thank you

  2. Hello,
    can you tell me please what to put into the

    app/code/mymodule/wishlist folder?

    I now have

    etc/
    routes.xml & di.xml

    controller/Index
    Add.php

    routes.xml:

    di.xml

    But it isnt working.

    Do I have to copy all of the magento_wishlist folder contents?

    Thanks!

    • Article assume that you already has a module. It should contain basic module files.
      – registration.php
      – /etc/module.xml

Leave a Reply

Your email address will not be published. Required fields are marked *