Ajax Based Add Product to Wishlist and Compare Products

In this blog post we will see how to make “Add to Wishlist” and “Add to Compare” operations ajax based.

In both product page and category page we will make the required changes for this. This is in continuation of the previous blog written for magento ajax based operations. Again we will use jquery for all ajax operations.
Attached are screenshots of the final result of this module

Ajax Wishlist and Compare Category Page

Ajax Wishlist and Compare Category Page

Ajax Wishlist and Compare Product Page

Ajax Wishlist and Compare Product Page

Also attached is the module created for this blog, it contains detailed source for each of the files.
[dm]19[/dm]
Now let see the steps to do this.

Product Page

The phtml file from where the Wishlist and Compare links come are catalog/product/view/addto.phtml. So first we will override this file so that we can put in our of javascript functions. To do this in our layout file we will put in this code

<catalog_product_view>
	   	<reference name='product.info.addto'>
	   		<action method='setTemplate'><template>ajaxwishlist/catalog/product/view/addto.phtml</template></action>
	   	</reference>
   </catalog_product_view>

So here we have set the template of the block ‘product.info.addto’ to ajaxwishlist/catalog/product/view/addto.phtml. In the new addtophtml we will place our new html code.
Wishlist
Now first let us see the html and javascript changes for the ‘Add To Wishlist’ link.
The default html of ‘Add to Wishlist’ is

<li><a href="<?php echo $_wishlistSubmitUrl ?>" onclick="productAddToCartForm.submitLight(this, '<?php echo $_wishlistSubmitUrl ?>'); return false;" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>

we will change this to

<li><a href="#" onclick="wishlistForm.submitAjaxWishlist(this, '<?php echo $_wishlistSubmitUrl ?>','<?php echo $_product->getId()?>'); return false;" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>

Next we will create the javascript of the wishlistForm used above.

<script type="text/javascript">
var wishlistForm = new VarienForm('product_addtocart_form');
wishlistForm.submitAjaxWishlist = function(button, url,id){
    if(this.validator) {
        var nv = Validation.methods;
        delete Validation.methods['required-entry'];
        delete Validation.methods['validate-one-required'];
        delete Validation.methods['validate-one-required-by-name'];
        if (this.validator.validate()) {
        	url = url.replace("wishlist/index","ajaxwishlist/index");
        	var data = jQuery('#product_addtocart_form').serialize();
			data += '&isAjax=1';
			jQuery('#ajax_loading'+id).show();
			jQuery.ajax( {
				url : url,
				dataType : 'json',
				type : 'post',
				data : data,
				success : function(data) {
					jQuery('#ajax_loading'+id).hide();
					if(data.status == 'ERROR'){
						alert(data.message);
					}else{
						alert(data.message);
						if(jQuery('.block-wishlist').length){
                            jQuery('.block-wishlist').replaceWith(data.sidebar);
                        }else{
                            if(jQuery('.col-right').length){
                            	jQuery('.col-right').prepend(data.sidebar);
                            }
                        }
                        if(jQuery('.header .links').length){
                            jQuery('.header .links').replaceWith(data.toplink);
                        }
					}
				}
			});
        }
        Object.extend(Validation.methods, nv);
    }
}.bind(wishlistForm);
</script>

The main code to note here is this

url = url.replace("wishlist/index","ajaxwishlist/index");
var data = jQuery('#product_addtocart_form').serialize();

we change the default wishlist url to our module’s url and in data variable serialize the forms fields. then ajax call is made to the URL and html is returned in appended to the right column.
Next we need to add code to the IndexController for this ajax action.

protected function _getWishlist()
	{
		$wishlist = Mage::registry('wishlist');
		if ($wishlist) {
			return $wishlist;
		}

		try {
			$wishlist = Mage::getModel('wishlist/wishlist')
			->loadByCustomer(Mage::getSingleton('customer/session')->getCustomer(), true);
			Mage::register('wishlist', $wishlist);
		} catch (Mage_Core_Exception $e) {
			Mage::getSingleton('wishlist/session')->addError($e->getMessage());
		} catch (Exception $e) {
			Mage::getSingleton('wishlist/session')->addException($e,
			Mage::helper('wishlist')->__('Cannot create wishlist.')
			);
			return false;
		}

		return $wishlist;
	}
	public function addAction()
	{

		$response = array();
		if (!Mage::getStoreConfigFlag('wishlist/general/active')) {
			$response['status'] = 'ERROR';
			$response['message'] = $this->__('Wishlist Has Been Disabled By Admin');
		}
		if(!Mage::getSingleton('customer/session')->isLoggedIn()){
			$response['status'] = 'ERROR';
			$response['message'] = $this->__('Please Login First');
		}

		if(empty($response)){
			$session = Mage::getSingleton('customer/session');
			$wishlist = $this->_getWishlist();
			if (!$wishlist) {
				$response['status'] = 'ERROR';
				$response['message'] = $this->__('Unable to Create Wishlist');
			}else{

				$productId = (int) $this->getRequest()->getParam('product');
				if (!$productId) {
					$response['status'] = 'ERROR';
					$response['message'] = $this->__('Product Not Found');
				}else{

					$product = Mage::getModel('catalog/product')->load($productId);
					if (!$product->getId() || !$product->isVisibleInCatalog()) {
						$response['status'] = 'ERROR';
						$response['message'] = $this->__('Cannot specify product.');
					}else{

						try {
							$requestParams = $this->getRequest()->getParams();
							$buyRequest = new Varien_Object($requestParams);

							$result = $wishlist->addNewItem($product, $buyRequest);
							if (is_string($result)) {
								Mage::throwException($result);
							}
							$wishlist->save();

							Mage::dispatchEvent(
                				'wishlist_add_product',
							array(
			                    'wishlist'  => $wishlist,
			                    'product'   => $product,
			                    'item'      => $result
							)
							);

							Mage::helper('wishlist')->calculate();

							$message = $this->__('%1$s has been added to your wishlist.', $product->getName(), $referer);
							$response['status'] = 'SUCCESS';
							$response['message'] = $message;

							Mage::unregister('wishlist');

							$this->loadLayout();
							$toplink = $this->getLayout()->getBlock('top.links')->toHtml();
							$sidebar_block = $this->getLayout()->getBlock('wishlist_sidebar');
							$sidebar = $sidebar_block->toHtml();
							$response['toplink'] = $toplink;
							$response['sidebar'] = $sidebar;
						}
						catch (Mage_Core_Exception $e) {
							$response['status'] = 'ERROR';
							$response['message'] = $this->__('An error occurred while adding item to wishlist: %s', $e->getMessage());
						}
						catch (Exception $e) {
							mage::log($e->getMessage());
							$response['status'] = 'ERROR';
							$response['message'] = $this->__('An error occurred while adding item to wishlist.');
						}
					}
				}
			}

		}
		$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
		return;
	}

This is the code required to make the ajax wishlist work.
Compare Link
This is the default code for the compare links

<li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>

we will change this to

<li><span class="separator">|</span> <a href="#" onclick="ajaxCompare('<?php echo $_compareUrl?>','<?php echo $_product->getId()?>'); return false;" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>

Here we have created a function called ajaxCompare() for the ajax operations. The code of ajax compare function is

function ajaxCompare(url,id){
	url = url.replace("catalog/product_compare/add","ajaxwishlist/index/compare");
	url += 'isAjax/1/';
	jQuery('#ajax_loading'+id).show();
	jQuery.ajax( {
		url : url,
		dataType : 'json',
		success : function(data) {
			jQuery('#ajax_loading'+id).hide();
			if(data.status == 'ERROR'){
				alert(data.message);
			}else{
				alert(data.message);
				if(jQuery('.block-compare').length){
                    jQuery('.block-compare').replaceWith(data.sidebar);
                }else{
                    if(jQuery('.col-right').length){
                    	jQuery('.col-right').prepend(data.sidebar);
                    }
                }
			}
		}
	});
}

Here also we have replaced the default compare url to our modules url. So here the implantation of the compareAction()

public function compareAction(){
		$response = array();

		if ($productId = (int) $this->getRequest()->getParam('product')) {
			$product = Mage::getModel('catalog/product')
			->setStoreId(Mage::app()->getStore()->getId())
			->load($productId);

			if ($product->getId()/* && !$product->isSuper()*/) {
				Mage::getSingleton('catalog/product_compare_list')->addProduct($product);
				$response['status'] = 'SUCCESS';
				$response['message'] = $this->__('The product %s has been added to comparison list.', Mage::helper('core')->escapeHtml($product->getName()));
				Mage::register('referrer_url', $this->_getRefererUrl());
				Mage::helper('catalog/product_compare')->calculate();
				Mage::dispatchEvent('catalog_product_compare_add_product', array('product'=>$product));
				$this->loadLayout();
				$sidebar_block = $this->getLayout()->getBlock('catalog.compare.sidebar');
				$sidebar_block->setTemplate('ajaxwishlist/catalog/product/compare/sidebar.phtml');
				$sidebar = $sidebar_block->toHtml();
				$response['sidebar'] = $sidebar;
			}
		}
		$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
		return;
	}

This is all that is required to make the compare link work.

Category Page

To make changes to the catagory page, we need to override the list.phtml file. To do this in the modules layout file put in this code

<catalog_category_default>
   		<reference name="head">
            <action method="addItem"><type>js</type><name>jquery/jquery-1.6.4.min.js</name></action>
            <action method="addItem"><type>js</type><name>jquery/noconflict.js</name></action>
            <action method="addItem"><type>skin_js</type><name>js/ajaxwishlist/ajaxwishlist.js</name></action>
        </reference>
    	<reference name='product_list'>
    		<action method='setTemplate'><template>ajaxwishlist/catalog/product/list.phtml</template></action>
    	</reference>
    </catalog_category_default>
    <catalog_category_layered>
    	<reference name="head">
            <action method="addItem"><type>js</type><name>jquery/jquery-1.6.4.min.js</name></action>
            <action method="addItem"><type>js</type><name>jquery/noconflict.js</name></action>
            <action method="addItem"><type>skin_js</type><name>js/ajaxwishlist/ajaxwishlist.js</name></action>
        </reference>
    	<reference name='product_list'>
    		<action method='setTemplate'><template>ajaxwishlist/catalog/product/list.phtml</template></action>
    	</reference>
    </catalog_category_layered>

Next in our layout file we need to change the code of ‘Add to wishlist’ and ‘Add to compare’. Default code is

<?php if ($this->helper('wishlist')->isAllow()) : ?>
                            <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
                        <?php endif; ?>
                        <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
                            <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
                        <?php endif; ?>

this needs to be changed to

<ul class="add-to-links">
                        <?php if ($this->helper('wishlist')->isAllow()) : ?>
                            <li><a href="#" onclick='ajaxWishlist("<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>","<?php echo $_product->getId()?>");return false;' class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
                        <?php endif; ?>
                        <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
                            <li><span class="separator">|</span> <a href="#" onclick='ajaxCompare("<?php echo $_compareUrl ?>","<?php echo $_product->getId()?>");return false;' class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
                        <?php endif; ?>
                    </ul>
                    <span id='ajax_loading<?php echo $_product->getId()?>' style='display:none'><img src='<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif')?>'/></span>

The ajaxCompare is the same function used previously. The new function created is ajaxWishlist. the code for which is

function ajaxWishlist(url,id){
	url = url.replace("wishlist/index","ajaxwishlist/index");
	url += 'isAjax/1/';
	jQuery('#ajax_loading'+id).show();
	jQuery.ajax( {
		url : url,
		dataType : 'json',
		success : function(data) {
			jQuery('#ajax_loading'+id).hide();
			if(data.status == 'ERROR'){
				alert(data.message);
			}else{
				alert(data.message);
				if(jQuery('.block-wishlist').length){
                    jQuery('.block-wishlist').replaceWith(data.sidebar);
                }else{
                    if(jQuery('.col-right').length){
                    	jQuery('.col-right').prepend(data.sidebar);
                    }
                }
			}
		}
	});
}
The detailed source code for making this work is attached in the zip file. Please upload it to your magento and checkout all files. Some files have not been explained this blog because of complexity, which are these in the module source code.
  • Hello, 
    I install this feature but it disabled the add to cart ajax module..

    Thanks, 
    Zanias Pantelis 

    • Manish Prakash

      Yes, please look at the layout xml code is detail. Both use separate list.phtml file, so you need to combine them smartly for both of them to work.

      • hello,
        I will combine them via xml file? Because i fixed in product addtocart but i can’t fix in category

        Thanks! 🙂

  • Roberto

    Hello, I have always this Alert Error: Pleas Login first, also if a user is logged in…

    • Manish Prakash

      Can you send the URL of your site.

      And which magento version are you using?

  • Anon

    Thank you Manish, it works and you have teach me something new. God bless

  • Hello, 

    Thanks for sharing this code. 
    What happens when a guest clicks on the link ? Does it require login from the user ?

    • Manish Prakash

      No it just shows a alert box that user needs to login

      • Neha

        So, its functionality is like : If a user is not logeed in. It will show an alert box.
        And if a user is logged in, it will add to wishlist via ajax.

  • Arshad Ali

    When we click on Add to Compare… it does not work with me. In firefox firebug..following msg comes:

    Call to a member function toHtml() on a non-object in /home2/inventor/public_html/app/code/community/VS/Ajax/controllers/WhishlistController.php

    And spinner continuously spins.

    What could be wrong and can any body help me?

  • Arshad Ali

    Hello Mustafa,
    Did u get the solution for that?
    Now i have the same issue almost. Now when i click on Add to Compare it shows me following message in firebug console i.e.

    Fatal error: Call to a member function setTemplate() on a non-object in /home2/inventor/public_html/app/code/community/VS/Ajax/controllers/WhishlistController.php on line 25

    So still no gud luck to solve this issue.

    Please any body can help me?

  • berengar

    hi,

    if I use web/secure/base_url with http://… it works fine but if I include https:// it just stops working. is this a common issue?

  • Swetha

    How to combine this with default magento’s add to wishlist functionality. I’m afraid “Add to Cart” from “My Wishlist” page for configurable products don’t work. Its being re directed to respective product details page if item options are not chosen earlier. Then if we choose and click “Add to Cart” it goes on an infinite loop without re directing to shopping cart page. But the product is added to cart successfully along with chosen options. Can you pl help.

  • Amish

    if user is logout and click on Add to wishlist button then its asking for login and once user login then page redirect to wishlist page and display response message in page pls solve this
    i want side bar instead of response message in body

  • Susanta

    Thank Deeepak

  • Veron

    [dm]19[/dm]
    Looks like attachment does not work. Can you please correct this?