FROM CACHE - en_header

Adding Multiple Products to Cart on One Click

rumleydev
Excursionist
21 4 1

I am attempting to post 2 items to a shopping cart, in one click. I've built a form with hidden checkboxes that carry the relevant product attributes I need to do that. I have a loop going over the form's child checkboxes to pull that info and invoke the function for the post request.

The problem is that sometimes it does add both items (yay!) but sometimes it'll load only the first item and sometimes only the second item. There's no error code in the console for me to go off of so I'm wondering what I'm missing.

I think it has something to do with asynchronous requests being made. I can see both requests firing off in the network tab of my Chrome Dev Tools. But I'm not sure how to implement that here.

The HTML:

<div id="form-wrapper">
    <form id='free-addon-form'>
        <input 
           type="checkbox" 
           name="paid-plan" 
           id="paid-plan-option-annual"
           data-variant-id="{{ p_annual.selected_or_first_available_variant.metafields.subscriptions.discount_variant_id }}" 
           data-variant-interval-value="{{ p_annual.metafields.subscriptions.shipping_interval_frequency }}" 
           data-variant-interval-unit="{{ p_annual.metafields.subscriptions.shipping_interval_unit_type }}"
           data-quickadd-id="{{ p_annual.selected_or_first_available_variant.id }}"
           data-quickadd-properties
           checked    
       >
       <input 
           type="checkbox" 
           name="free-addon" 
           id="paid-plan-option-freebie"
           data-variant-id="{{ p_free.selected_or_first_available_variant.metafields.subscriptions.discount_variant_id }}"
           data-quickadd-id="{{ p_free.selected_or_first_available_variant.id }}"
           data-quickadd-properties
           checked    
       >
       <button class="btn"
               type="submit" 
               name="free-addon-submit" 
               id="" 
       >
       {{ p_annual.selected_or_first_available_variant.price | money_without_trailing_zeros }}{{ section.settings.productlink1label }}
       </button>
    </form>
</div>

 
My JS

const freeAddOnForm = document.getElementById('free-addon-form'),
      freeAddOnButton = freeAddOnForm[2];

function getDataForm(e) {
    e.preventDefault();

    loadingBarTrigger('start');

    for(let i = 0; i < 2; i++) {
        itemAdd(
            freeAddOnForm[i].getAttribute('data-quickadd-id'), 
            freeAddOnForm[i].getAttribute('data-quickadd-properties'), 
            (freeAddOnForm[i].getAttribute('data-quickadd-quantity'))
                ? freeAddOnForm[i].getAttribute('data-quickadd-quantity')
                : 1, 
            (!html.is('#cart')) ? true : false,
            (html.is('#cart')) ? true : false
        )
    }   
}

document.addEventListener('DOMContentLoaded', function (){
    freeAddOnButton.addEventListener('click', getDataForm, false);
})

 

The theme's code for adding a single item that I was trying to replicate:

_document.on('click', '[data-quickadd-id]', function() {
    let _this = $(this);

    loadingBarTrigger('start');

    itemAdd(
        _this.attr('data-quickadd-id'), 
        _this.attr('data-quickadd-properties'), 
        (_this.attr('data-quickadd-quantity'))
            ? _this.attr('data-quickadd-quantity')
            : 1, 
        (!html.is('#cart')) ? true : false,
        (html.is('#cart')) ? true : false
    );
});

 

The itemAdd function that makes the post request to the cart:

const itemAdd = (variantId, properties, qty, openCart, reloadPage) => {
    $.ajax({
        type: 'POST',
        dataType: 'html',
        url: `/cart/add.js`,
        data: 
            {
                id: variantId,
                quantity: qty,
                properties: (properties) 
                    ? JSON.parse(properties) : null
            },
        error: function(data) {
            console.error(data);

            loadingBarTrigger('done');
        },
        success: function() {
            loadingBarTrigger('move');

            $.ajax({
                url: '/cart',
                dataType: 'html',
                error: function(data) {
                console.error(data);

                loadingBarTrigger('done');
            },
                success: function(data) {
                    let minicartContent = $('#minicart-content');
                    let cartItemsHtml = $(data).find('#cart-content #cart-items').html();

                    // insert or prepend cart HTML
                    (minicartContent.find('#cart-items').length)
                        ? minicartContent.find('#cart-items').html(cartItemsHtml)
                        : minicartContent.prepend(cartItemsHtml);

                    // remove giftbox content if exists
                    (minicartContent.find('#cart-giftbox .item-info').length)
                        ? minicartContent.find('#cart-giftbox .item-info').remove()
                        : '';

                    loadingBarTrigger('done');
                    cartTotalUpdate();

                    // open cart
                    (openCart && !html.is('#cart'))
                        ? minicartTrigger.trigger('click') : '';

                    (reloadPage)
                        ? location.reload() : '';
                }
            });
        }
    });
}

 

Thoughts?

Replies 3 (3)
rumleydev
Excursionist
21 4 1
rumleydev
Excursionist
21 4 1

Thinking that it's the open cart function at the end of itemAdd that is causing the problem. Both request are being made and returned. Unsure where to put that logic though.

rumleydev
Excursionist
21 4 1

Here's a blog post that describes my issue. I'm going to have to build an array of objects to push to the itemAdd function.

http://www.codeshopify.com/blog_posts/how-to-add-multiple-products-with-an-ajax-cart