This post is a bit over­due con­sid­er­ing the project for which I did this was com­pleted months ago. I finally got around to doc­u­ment­ing it. Magento’s prod­uct list view lets cus­tomers add prod­ucts to the shop­ping cart one at a time. The client wanted cus­tomers to be able to add mul­ti­ple prod­ucts to the shop­ping cart simul­ta­ne­ously. Given the time con­straints for the projects, I cre­ated an ad hoc AJAX method to accom­plish this fea­ture request.

Adding a prod­uct to a Magento (ver. 1.3.1) shop­ping cart is accom­plished through an HTTP GET request. It will look like or sim­i­lar to this:

/path/to/app/checkout/cart/add?product=[id]&qty=[qty]

That URL is out­put by the tem­plate helper:

$this->getAddToCartUrl($_product)

Since adding a prod­uct to the shop­ping cart is noth­ing more than a GET request, then all that needs to be done is queue up the URLs of the desired prod­ucts, make each request in order, and then reload the page when done.

First, in app/design/frontend/ / /template/catalog/product/list.html, I first added check­boxes to allow cus­tomers to select which prod­ucts they want and also hid­den fields for stor­ing the URLs to add the prod­uct and text fields for the quantity.

<input type="checkbox" class="input-checkbox add" name="add_<?php echo $_iterator; ?>" id="add_<?php echo $_iterator; ?>" />
<input type="hidden" name="url_<?php echo $_iterator; ?>" id="url_<?php echo $_iterator; ?>" value="<?php echo $this->getAddToCartUrl($_product) ?>" />
<?php if(!$_product->isGrouped()): ?>
     <input type="text" class="input-text qty" name="qty_<?php echo $_iterator; ?>" id="qty_<?php echo $_iterator; ?>" maxlength="12" value="<?php echo $this->getMinimalQty($_product) ?>" />
<?php endif; ?>

I added this code within the loop that gen­er­ate the HTML for the prod­uct line items for the list. Next, I added the JavaScript that does the actual pro­cess­ing, also within the list sec­tion right after the script block that con­tains: decorateList('products-list', 'none-recursive').

<script type="text/javascript">
    function processNext(urls, i) {
        var next = i + 1;
        $('processing-text').update('Processing item ' + next);
        if (next < urls.size()) {
            new Ajax.Request(urls[i], {
              method: 'get',
              onComplete: function(transport) {
                processNext(urls, next);
              }
            });
        } else {
            new Ajax.Request(urls[i], {
              method: 'get',
              onComplete: function(transport) {
                window.location.reload();
              }
            });
        }
    }

    function addItemsToCart() {
        $('add-items-to-cart').hide();
        $('waiting').show();
        
        var addToCartUrls = [];
        $$('input.add').each(function(e){ 
            if(e.checked == true) {
                var id = e.readAttribute('id').split('_')[1];
                var qty = Number($('qty_' + id).value);
                if (qty < 1) qty = 1;
                addToCartUrls.push($('url_' + id).value + 'qty/' + qty);
            }
        });
        
        if (addToCartUrls.size() > 0) {
            processNext(addToCartUrls, 0);
        } else {
            $('add-items-to-cart').show();
            $('waiting').hide();
            alert('Please check off the items you want to add.');
        }
    }
</script>

At the bot­tom of the list I added a sub­mit button.

<div style="margin-bottom:5px; text-align:right;"><button id="add-items-to-cart" class="form-button" onclick="addItemsToCart()"><span><?php echo $this->__('Add Items to Cart') ?></span></button><div id="waiting" style="height:22px; display:none; line-height:22px;"><span id="processing-text">Processing...</span> <img src="<?php echo $this->getSkinUrl().'images/wait22trans.gif'; ?>" width="22" height="22" style="display:inline; vertical-align:middle;"/></div></div>

Click­ing the but­ton calls the func­tion addItemsToCart(). The func­tion hides the but­ton to pre­vent a dou­ble click and unhides the sta­tus mes­sage. Next, the func­tion deter­mines which check­boxes are checked. For each checked check­box, the func­tion finds the cor­re­spond­ing URL field and quan­tity field, con­cate­nates the two val­ues, and stores the new URL in an array. If the length of the array is greater than 0, then the func­tion calls processNext(), oth­er­wise it dis­plays an error mes­sage and resets the sub­mit button.

The func­tion processNext() first updates the pro­cess­ing mes­sage. The func­tion takes the array of URLs and an index, and then cre­ates an AJAX GET request using the URL at the given index in the array. If the AJAX request com­pletes, it calls process­Next() with the same array but with an incre­mented index while the index is less than the array length. If the incre­mented index is greater than the array length, then that ends the pro­cess­ing and the func­tion reloads the page.

That’s it. If there is any­thing wrong with the code, it assumes that all the GET requests will com­plete. Unfor­tu­nately, given the time con­straints there was no time to account for the sce­nario where a GET request fails.

9 Responses to “How To Simultaneously Add Multiple Products To A Magento Shopping Cart”

  1. benabbas amine said on September 8th, 2010 at 6:53 pm:

    Nice work, but when we click on add items to cart, they are going to Recently Viewed Prod­ucts instead .… Any idea about this, have you updated your codes …

    Thanks

  2. Brian said on September 8th, 2010 at 9:24 pm:

    I have no idea. I have not updated the code for the lat­est ver­sion of Magento.

  3. Erin said on December 8th, 2010 at 8:13 am:

    Hi Brian,

    Thank you for this post. I know this is a lit­tle off topic but — Do you have any idea how to imple­ment this idea for the Prod­uct Com­pare func­tion rather than the cart? I.e. if I have mul­ti­ple prod­ucts listed,I would like to check off the ones I want to com­pare and click “Com­pare Prod­ucts” and have all the prod­ucts I checked off added to the com­pare popup?

    Thank you!

    Erin

  4. Brian said on December 8th, 2010 at 6:13 pm:

    @Erin

    Unfor­tu­nately, I’m not famil­iar with the Prod­uct Com­pare func­tion and so I don’t know if this tech­nique is applicable.

  5. WebbOn said on March 2nd, 2011 at 8:56 am:

    Hello.
    I’m try­ing to get it to work on the cus­tom tem­plate, where I show all items from all cat­e­gories by using the getItems () as $ _product):?>
    Script pro­cess­ing checked items but does not save the prod­ucts in cart, the page just restarts.

    This is my code:
    helper (‘cat­a­log / out­put’);
    $ prod­uct = Mage:: get­Model (‘cat­a­log / prod­uct’);
    $ Pro­duct­Name col­lec­tion = $ product-> get­Col­lec­tion () -> addAt­trib­ut­e­ToS­e­lect (‘*’);
    $ _product = $ this-> get­Prod­uct ();
    ?>
    getItems () as $ _product):?>
    <a href = ” get­Pro­duc­tUrl ()?>”> get­Name ()?>
    <a href = ” get­Pro­duc­tUrl ()?>”> get­Sku ()?>
    get­Price ()?>

  6. codered said on March 2nd, 2011 at 2:40 pm:

    Hi! how about update script to use with magento 1.5.0.1 there addto­cartlink looks like /checkout/cart/add/product/25/qty/3

  7. Alex said on June 23rd, 2011 at 1:06 am:

    Regard­ing ear­lier com­ment, this can be used for a prod­uct com­pare select list in 1.5. Only edit I made was to remove the quan­tity field from the html and also from the addItem­sTo­Cart func­tion. Thanks Brian, very useful.

    I also added an ajax load­ing gif — here’s a great resource with loads of options if you need one: http://www.ajaxload.info/

  8. nick said on October 11th, 2011 at 1:25 am:

    Regard­ing on Alex’s com­ment about mul­ti­ple prod­ucts in com­pare i would like to know how is that possible?I did every­thing (replace the quan­tity and replace addto­card with addto­com­pare (wrong func­tion?), ajax proc­cess­ing the items but adding only 1 item. I am try­ing 4 hours now… any help?

  9. nick said on October 11th, 2011 at 4:13 am:

    i had a typo error, now its ok

Subscribe to this post/thread