4

How do I update the lineItems after I submit the form through ajax? right now it adds the item, but it doesn't show up in the cart, it only shows up when I reload the page.

I am adding an item to the cart through ajax with this code:

$('.form-products').on('submit', function(e) {

    e.preventDefault();

    var data = $(this).serialize();

    $.ajax({
        type: 'POST',
        data: data,
        url: '/',
        success: function(response) {
            var cartCount = '(' + response.cart.totalQty + ')';
            $('.cart-count').text(cartCount);

            $('#cart').removeClass('close');
        },
        error: function(response) {
            console.log(response);
        }
    });

});

Then under the div#cart I have this code:

{% for item in cart.lineItems %}
   <li>
     cart information goes here
     this shows the product images, price and other info.
   </li>
{% endfor %}

1 Answer 1

4

There are two major approaches.

  1. The easier approach is to create a partial template that displays the cart lineItems, and simply ajax load that template in to a div that is your cart display after you've done the lineItem update. However, this has the disadvantage of making the whole cart section update in a visible way, which look a lot less finessed than the second approach.

  2. In short, you'll need to use the cart object in the json response to re-draw just the appropriate parts of your cart display.

Here's an example of approach 2, (don't focus on the specifics below which are from a live site - but rather this should be enough to give you the idea) - if the user e.g. adjusts line item quantities, we grab the appropriate parts of response.cart and then do some local calculations and update the appropriate parts of the page:

            $.post('/actions/' + $('input[name=action]').val(), form.serialize(), function(response) {

            // Change in qty successful
            if (response.success) {
                if (response.cart.lineItems[id]) {
                    var subtotalNew = parseFloat(response.cart.lineItems[id].price * response.cart.lineItems[id].qty);
                    utilities.replacePrice($subtotal, subtotalNew);
                }

                navCart.update(response.cart);
                cart.update(response.cart, true);
            }

...where, for example, utilities.replacePrice is:

replacePrice: function($obj, price, discount) {
    var text = module.exports.currency(price);

    // Handle discounts
    if (discount) {
        // Supplied as negative number - because we want it formatted differently, we make it positive
        var discountPrice = module.exports.currency(price * -1);
        text = '- (' + discountPrice + ')';
    }

    $obj.fadeOut("fast", function(){
        $obj.text( text );
        $obj.fadeIn("fast");
    });
},

...and the cart.update functions are similar and take care of updating the nav bar cart and the totals and shipping sections.

I will warn you that implementing in full a completley ajax updating cart page is a fair bit of work and complexity to get right, and the actual implementation will depend greatly on your checkout flow, which you should have thoroughly worked out BEFORE you implement this, or you can quickly tie yourself in JS knots.

If you want to see a fairly completely ajaxed Commerce cart in action, add this to your cart and then visit your cart and muck about changing quantities and removing things etc: https://imagescience.com.au/products/inkjet-print-retouching-kit

1
  • I see, so I just take all the attributes that I need from the lineItem like the images and description and then when the user updates the quantity I'll update the cart from the response.cart, that makes sense. Thanks a lot Jeremy Mar 30, 2017 at 13:17

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.