6

I've asked a similar question before, but because of some research, it would not have been relevant anymore. So here a more comprehensive explanation of my problem.

My scenario

I want the cart page to update without a refresh when the quantity has been changed of a product in the order list.

What I did

First of all, and most essential in this whole problem: I reinstalled Magento so there was a clean work environment I could test the module in. Secondly, I created a module, named AjaxCart. This module consists of the following files:

Directory breakdown

module.xml has the following content:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_AjaxCart" setup_version="2.0.0"/>
</config>

checkout_cart_index.xml has the following content:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <link src="Vendor_AjaxCart/js/jquery.cartAjaxQty.js"/>
    </head>
</page>

requirejs-config.js has the following content:

var config = {
    map: {
        '*': {
            ajaxQty: 'Vendor_AjaxCart/js/jquery.cartAjaxQty'
        }
    }
};

and finally jquery.cartAjax.js has the following content:

    require(['jquery', 'Magento_Checkout/js/action/get-totals'], function () {
    jQuery(document).ready(function($, getTotalsAction){
        $(".cart-container .form-cart .action.update").remove();
        // On change handler
        jQuery(document).on('change', 'input[name$="[qty]"]', function(){
                    console.log("quantity changed");
                    var form = jQuery(jQuery(this).closest('form'));

                    $.ajax({
                        url: form.attr('action'),
                        data: form.serialize(),
                        showLoader: true,
                        context: this.changedInput,
                        success: function (res) {
                            var parsedResponse = $.parseHTML(res);
                            var result = $(parsedResponse).find("#form-validate");
                            $("#form-validate").replaceWith(result);
                            var deferred = $.Deferred();
                            getTotalsAction([], deferred);
                            console.log('Ajax succes function completed');
                        },
                        error: function (xhr, status, error) {
                            var err = eval("(" + xhr.responseText + ")");
                            console.log(err.Message);
                        }
                    });

                }
            );
    });
});

So, I also know where things go wrong: the requirements. If the file only has the following requirement:

require([
    'jquery']

There is nothing wrong, and I can console.log the changes in quantities.

Problem

If I add the requirement I have in the file (which I need to update the cart summary block), I get the following error on the cart page:

sectionloadurl error

I don't know if this is a Magento 2.2.x bug, or is it because of the file or directory structures I have made. Anyhow, it is something that has me in it's grip for a long time and I am really thinking this is just a problem caused by Magento self and not my code.

I'm really curious if someone could try exactly what I did (except the clean install, a little bit too much to ask) and see if he/she gets the same problem or if someone knows an answer to this. I've also tried changing themes, but no luck.

-- ADITIONAL INFO --

I've tried to perform a change on the cart in Firefox, but upon showing the page (like in Chrome), Firefox also throws an error, but this time a different one:

options is not defined

So I've followed this question:

TypeError: options is undefined (customer-data.js)

But no luck.

-- Update --

As Pascal Wientjes pointed out, I should use define instead of require. I did this, and than the following error occured:

Define error

This could be fixed by changing the requirejs-config.js file to:

var config = {
map: {
    '*': {
        ajaxQty: 'Vendor_AjaxCart/js/cartAjaxQty'
    }
},

deps: [
    "Vendor/js/cartAjaxQty"
]

};

And stop including the jquery.cartAjax.js in the head of checkout_cart_index.xml. But unfortunately, the old error shows up again.

If of any use: when included using above way, the file is loaded on every page of course. For example, when browsing to the home page, the following errors also show up, but this is probably because of the information it is missing on those pages (just providing as much information as possible):

storecode and quotedata error

-- Update --

Sometimes, really sometimes, the page somehow loads correctly, even while customer-data.js is loaded AFTER cartAjaxQty.js. You can see I have a console.log("running"); inside my code which is printend in the console:

enter image description here

  • Did you try to add the section Magento_Checkout to your module.xml? It is mandatory to use section because of module loading order it may cause some dependency issues. Run a bin/magento setup:upgrade to reorganise your app/etc/config.php file and so the loading order. – Matthéo Geoffray Apr 11 '18 at 9:46
  • This question may help - magento.stackexchange.com/questions/160707/… – Ben Crook Apr 11 '18 at 9:49
  • @MatthéoGeoffray Okay, I did. Module_AjaxCart is above in the list, above Magento_Checkout. This means Module_AjaxCart is being loaded before Magento_Checkout? And that can cause the error? – Condor Apr 11 '18 at 9:51
  • @BenCrook I've already tried that and did not help unfortunately – Condor Apr 11 '18 at 9:52
  • @MatthéoGeoffray I've set the sequence like so: <module name="Module_AjaxCart" setup_version="2.0.0"> <sequence> <module name="Magento_Checkout" /> </sequence> </module> and loads the Checkout before Module_AjaxCart but changes nothing unfortunately. – Condor Apr 11 '18 at 10:22
4
+25

You should use define in your jquery.cartAjax.js file instead of require, also pass $ as an argument so you can use it in the ajax call, require is specifically designed for phtml files and define for javascript files.

define([
       'jquery',
       'Magento_Checkout/js/action/get-totals'
       ], function ($, getTotalsAction) {

$(document).ready(function(){
    $(".cart-container .form-cart .action.update").remove();
    // On change handler
    jQuery(document).on('change', 'input[name$="[qty]"]', function(){
                console.log("quantity changed");
                var form = jQuery(jQuery(this).closest('form'));

                $.ajax({
                    url: form.attr('action'),
                    data: form.serialize(),
                    showLoader: true,
                    context: this.changedInput,
                    success: function (res) {
                        var parsedResponse = $.parseHTML(res);
                        var result = $(parsedResponse).find("#form-validate");
                        $("#form-validate").replaceWith(result);
                        var deferred = $.Deferred();
                        getTotalsAction([], deferred);
                        console.log('Ajax succes function completed');
                    },
                    error: function (xhr, status, error) {
                        var err = eval("(" + xhr.responseText + ")");
                        console.log(err.Message);
                    }
                });

            }
        );
    });
});

hope it helpes

Update:

i think there's also somehting going wrong with the call to the file

it should look somehting like this: <script>require(['ajaxQty']);</script> where ajaxQty is the name declared in the require-config.js

  • I've tried this before, and unfortunately it throws: Mismatched anonymous define() module: function ($, getTotalsAction) – Condor Apr 16 '18 at 15:00
  • I figured this is due to the fact that I load it in whilst using <script src="Module_AjaxCart/js/cartAjaxQty.js" /> to include it on the page within my checkout_cart_index.xml. When I use deps inside my require-js.config, the file won't throw above error anymore but than goes back to the old error.. – Condor Apr 17 '18 at 6:35
  • see updated answer – Pascal Wientjes Apr 17 '18 at 8:22
  • You mean like <script>require(['ajaxQty']);</script> to be included within the <head>-tag in checkout_cart_index.xml ? Because the script tag needs a src and can't have character content. – Condor Apr 17 '18 at 8:30
  • no no just anywhere in a phtml file, don't try to do anything in the head.. let require do all the work :p – Pascal Wientjes Apr 17 '18 at 8:32
2

Okay, I fixed it eventually, with help and thinking of Pascal Wientjes

So, when discussing about what the issue could be with said person, we came to the conclusion that customer-data.js was loaded after cartAjaxQty.js.

Even though I included the Magento_Customer module in a sequence-tag within the module.xml, still customer-data.js still got loaded AFTER my script. I posted a question about this:

<sequence> not working?

Where other people reacted, and so Magento loads customer-data.js via it's layout. So I had to figure out another way. Pascal told maybe you could use a $(document).ready, so I tried but no luck. I thought.

This eventually fixed it: $(window).on("load", function ()

My script.phtml eventually looks like this!

<script>
require ([
        'jquery'
    ],
function ($) {
    $(window).on("load", function () {
        require([
            'Vendor_AjaxCart/js/cartAjaxQty'
        ]);
    });
});

And now all loads fine. It's not the fix I had hoped for, a more cleaner approach would've been my preference but it fixes my error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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