2

I have been trying add products to cart via ajax call by following the procedure given in http://excellencemagentoblog.com/magento-add-product-to-cart-ajax and I have successfully added products to add too. But my problem is, while returning from ajax call, I'm trying to return updated cart count and mini cart html. But this is not working properly.

Following is my controller action

public function addAction(){

    $cart   = $this->_getCart();

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

    if($params['isAjax'] == 1){
        $response = array();
        try {
            if (isset($params['qty'])) {
                $filter = new Zend_Filter_LocalizedToNormalized(
                array('locale' => Mage::app()->getLocale()->getLocaleCode())
                );
                $params['qty'] = $filter->filter($params['qty']);
            }

            $product = $this->_initProduct();
            $related = $this->getRequest()->getParam('related_product');

            /**
             * Check product availability
             */
            if (!$product) {
                $response['status'] = 'ERROR';
                $response['message'] = $this->__('Unable to find Product ID');
            }

            $cart->addProduct($product, $params);
            if (!empty($related)) {
                $cart->addProductsByIds(explode(',', $related));
            }

            $cart->save();

            Mage::getSingleton('checkout/session')->setCartWasUpdated(true);

            /**
             * @todo remove wishlist observer processAddToCart
             */
            Mage::dispatchEvent('checkout_cart_add_product_complete',
            array('product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse())
            );

            if (!$this->_getSession()->getNoCartRedirect(true)) {
                if (!$cart->getQuote()->getHasError()){
                    $message = $this->__('%s was added to your shopping cart.', Mage::helper('core')->htmlEscape($product->getName()));
                    $response['status'] = 'SUCCESS';
                    $response['message'] = $message;
                    $this->loadLayout();
                    $toplink = Mage::helper('checkout/cart')->getSummaryCount();
                    $sidebar = $this->getLayout()->getBlock('minicart_content')->toHtml();
                    $response['count'] = $toplink;
                    $response['cartitems'] = $sidebar;
                }
            }
        } catch (Mage_Core_Exception $e) {
            $msg = "";
            if ($this->_getSession()->getUseNotice(true)) {
                $msg = $e->getMessage();
            } else {
                $messages = array_unique(explode("\n", $e->getMessage()));
                foreach ($messages as $message) {
                    $msg .= $message.'<br/>';
                }
            }

            $response['status'] = 'ERROR';
            $response['message'] = $msg;
        } catch (Exception $e) {
            $response['status'] = 'ERROR';
            $response['message'] = $this->__('Cannot add the item to shopping cart.');
            Mage::logException($e);
        }
        $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
        return;
    }else{
       return parent::addAction();
    }
}

Please help

1 Answer 1

5

This is easily done, but the javascript functions that trigger the minicart show/hide will "break", since you are reloading content into the DOM, which was instantiated at page load or document ready.

I'll show you how to achieve the result first, then we'll tackle the javascript issue.

Answering The Question

The block you want is called minicart_head, so your layout code in the controller addAction should be as follows:

if (!$this->_getSession()->getNoCartRedirect(true)) {
    if (!$cart->getQuote()->getHasError()){
        $message = $this->__('%s was added to your shopping cart.', Mage::helper('core')->htmlEscape($product->getName()));
        $response['status'] = 'SUCCESS';
        $response['message'] = $message;
        $this->loadLayout();
        $minicart = $this->getLayout()->getBlock('minicart_head')->toHtml(); // <-- here's the block
        $response['minicart'] = $minicart;
    }
}

You can use the minicart data to replace the DOM object from your javascript function.

try {
    jQuery.ajax({
        url: url,
        dataType: 'json',
        type : 'post',
        data: data,
        success: function(data){
            var json =  eval(data);
            jQuery('#ajax_loader').hide();
            if (jQuery('.header-minicart')) {
                jQuery('.header-minicart').html( json.minicart );
            }
        }
    });
} catch (e) {
}

If you observe the DOM, using Web Inspector, for example, you will see that the content updates now via AJAX, but your show/hide feature will no longer work, since the javascript that acts on the #header-cart link has not been triggered for the new content.

Javascript Issue

By using jQuery's .on(), the theme developers at magento are on the right track (although they use a convoluted procedure to update the cart via AJAX).

In order for the show/hide feature to work, you need to use .on() delegation, or bubbling. In app.js, find the following:

File: app/skin/frontend/rwd/default/js/app.js

var skipContents = $j('.skip-content');
var skipLinks = $j('.skip-link');

skipLinks.on('click', function (e) {
    ...
}

And replace it as follows:

var skipContents = $j('.skip-content');
var skipLinks = $j('.skip-link');

$j('.skip-links').on('click', '.skip-link', function (e) {
    ...
}

And there you have it. Now your content reloads via AJAX, and the links still work after the cart changes.

1
  • Thanks for your answer here - helps immensely. I have the cart working. I have ran into difficulty animating the load - I want the cart to dropdown for 2 seconds. I added 'skip-active' to jQuery('#header-cart') and prev(), then take the class off. After that the drop-down no longer works for the cart. Any ideas? Oct 2, 2014 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.