Magento 2 : Add to compare and add to wishlist with ajax

I have added Ajax add to wishlist functionality on product page following below method:

Added custom "Add to wishlist" button to following file inside <?php if ($block->isWishListAllowed()) : ?> condition

app/design/frontend/Vendor/Module/Magento_Wishlist/templates/catalog/product/view/addto/wishlist.phtml

<button name="add-to-wishlist" onclick="addProductToWishlist()"> Add to Wishlist</button>
<?php $productId = json_decode($block->getWishlistParams(), true)['data']['product']; ?>

It calls addProductToWishlist() javascript function which I have added in the same wishlist.phtml file

<script>
function addProductToWishlist() {
    require(["jquery"], function($){
        $.ajax({
            url: '<?php echo $this->getUrl('general/index/addtowishlist') ?>',
            method: 'get',
            data: { productId: <?php echo $productId ?>},
            dataType: 'json',
            showLoader:true,
            success: function(data){
                var redirect = data.result.redirect;
                if(redirect) {
                    window.location.href = '<?php echo $this->getUrl('customer/account/login') ?>';
                } else {
                  // show successfully added message 
                }
            }
        });
    });
}

Here is my controller code which has logic of adding product to wishlist.

app/code/Vendor/Module/Controller/Index/Addtowishlist.php

<?php

namespace Vendor\General\Controller\Index;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;

class Addtowishlist extends Action {

    protected $customerSession;
    protected $wishlistRepository;
    protected $productRepository;

    public function __construct(
    Context $context,
    \Magento\Customer\Model\Session $customerSession,
    \Magento\Wishlist\Model\WishlistFactory $wishlistRepository,
    \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
    ResultFactory $resultFactory,
    \Magento\Framework\Controller\Result\JsonFactory $jsonFactory
        ) {
        $this->customerSession = $customerSession;
        $this->wishlistRepository= $wishlistRepository;
        $this->productRepository = $productRepository;
        $this->resultFactory = $resultFactory;
        $this->jsonFactory = $jsonFactory;
        parent::__construct($context);
    }

    public function execute() {
        $customerId = $this->customerSession->getCustomer()->getId();
        if(!$customerId) {
           $jsonData = ['result' => ['status' => 200, 'redirect' => 1,'message' => 'Customer not logged in.']]; 
            $result = $this->jsonFactory->create()->setData($jsonData);
            return $result;
        }
        $productId = $this->getRequest()->getParam('productId');

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

        $wishlist = $this->wishlistRepository->create()->loadByCustomerId($customerId, true);

        $wishlist->addNewItem($product);
        $wishlist->save();

        $jsonData = ['result' => ['status' => 200, 'redirect' => 0, 'message' => 'Added to wishlist']];
        $result = $this->jsonFactory->create()->setData($jsonData);
        return $result;
    }
} 

Above code works fine on product page. Similar way you can add Ajax add to wishlist functionality on listing page.

Note: Above code needs some improvement like validating form_key in controller file.


I've managed to come up with a fairly simple solution for AJAX Wishlist functionality:

1) Use the following helper method which returns JSON-encoded parameters:

$this->helper("Magento\Wishlist\Helper\Data")->getAddParams($product)

This returns something like the following:

{
    "action": "https://www.mywebsite.com/wishlist/index/add/",
    "data": {
        "product": "1",
        "uenc": "a0bLy9tMhZGlhLWVsZXljbGFya2oZWxY29tL25i5hc3RsZW1lbnRzLXNUusLmhHR0cHM6Ww,"
    }
}

2) Include the form key in your data when making a POST request, similar to the following:

var url  = "https://www.mywebsite.com/wishlist/index/add/";
var data = {
    action   : "add-to-wishlist",
    form_key : "xyC5IcaqeNg2um6g",
    product  : "1",
    uenc     : "a0bLy9tMhZGlhLWVsZXljbGFya2oZWxY29tL25i5hc3RsZW1lbnRzLXNUusLmhHR0cHM6Ww,"
}

$.post(url, data);

The item should now be in your wishlist.

Note: the form key can be obtained either via JavaScript by getting the value of a cookie called form_key or through Magento's getFormKey() function.

Edit: there are a couple of drawbacks when using this method:

  1. There's no success callback from the POST request.
  2. Once you add an item, you'll see a message on the next page you visit saying "[item] has been added to your Wish List. Click here to continue shopping."

So although this works, it's far from a robust solution.

Tags:

Ajax

Magento2