Magento2 Ajax Add to Cart – Handle Out of Stock Situations

addtocartajaxcartjavascriptmagento2

I have implemented Ajax to my "Add to Cart" button so that customers can add products to their cart without reloading the page.

Here is bare minimum of code which I used in order to achieve successful Ajax call in Product Details page for adding Product to Cart without refresh:

<form method="post" action="<?php /* @escapeNotVerified */ echo $block->getSubmitUrl($_product); ?>" id="product_addtocart_form"<?php if ($_product->getOptions()) {echo ' enctype="multipart/form-data"';} ?>>
    <input type="hidden" name="product" value="<?php /* @escapeNotVerified */ echo $_product->getId(); ?>" />

    <button type="submit">Add to Cart</button>

    <script type="text/x-magento-init">
        {
            "#product_addtocart_form": {
                "catalogAddToCart": {
                    "bindSubmit": true
                }
            }
        }
    </script>
</form>

Well, this far everything works perfect. When the button is clicked, message appears in page about successful Product adding to Cart.

The problem is when Product cannot be added to Cart for some reason (for example, out of stock). Then instead of message showing in page dynamically, the refresh happens and only then message pops out in page.

How do I stop refresh in those cases and simply just show the message about reason why Product is not able to be added to Cart?

Best Answer

In order to achieve this, you need to follow these steps:

1) Override Magento2 default theme js file by copying it from this path: vendor/magento/module-catalog/view/frontend/web/js/catalog-add-to-cart.js (this is a path if you used composer for magento2 installation) to your custom theme path (may be a custom module as well, but in my case I had custom theme): app\design\frontend\TheBrewCompany\default\Magento_Catalog\web\js\catalog-add-to-cart.js

2) Find in code mage.catalogAddToCart widget -> ajaxSubmit function -> $.ajax call -> success call back -> and if (res.backUrl) statement (in my case it was line 86-88).

3) Delete code that is inside that if statement and leave it empty. These two lines:

window.location = res.backUrl;
return;


At this point the redirect will not happen anymore. But then comes next problem: message about reason why product could not be added to cart is not printed in web-site. Instead, it will be printed in next page load (refresh or page change). To print those messages, do following steps:

1) In the same catalog-add-to-cart.js file, at the top, define two more files:

'Magento_Customer/js/customer-data',
'jquery/jquery-storageapi'

2) In function declaration add two more arguments: _ and customerData

3) In the previously emptied if statement, insert this code:

customerData.reload('messages');


Done. At the end, the changes should look something like this: beginning of file:

    define([
    'jquery',
    'mage/translate',
    'jquery/ui',
    'Magento_Customer/js/customer-data',
    'jquery/jquery-storageapi'
], function($, $t, _, customerData) {

and ajax success callback:

if (res.backUrl) {
    customerData.reload('messages');
}


And final step: in order to make changes work, do following steps:

1) delete pub/static/frontend directory

2) run command php bin/magento setup:di:compile

3) run command php bin/magento setup:static-content:deploy

4) run command php bin/magento cache:flush