Trying to ajax add to cart but each submit returns a

https://www.website.com/commerce/cart/updateCart 404 (Not Found)

I have this in my twig template:

{% for book in craft.products().type('books').limit(8).all() %}
<a href="{{ book.url }}" class="book">
    {% for image in book.productImages.limit(1).all() %}
    <div class="b-img">
        <img src="{{ image.getUrl() }}" />
        <div class="hover-cart">
            <div class="success"><i class="fas fa-check-circle"></i></div>
            {% set variant = book.defaultVariant %}
            <form method="POST" class="add-to-cart">
                {{ csrfInput() }}
                <input type="hidden" name="purchasableId" value="{{ variant.id }}">
                <input type="number" name="qty" value="1">
                <button type="submit"><i class="fas fa-shopping-cart"></i></button>
            </form>
        </div>
    </div>
    {% endfor %}
    <h3>{{ book.title }}</h3>
    <span class="price">{{ book.defaultVariant.price|currency }}</span>
</a>
{% endfor %}

And this as my javascript:

$('.add-to-cart').on('submit', function(e) {
    console.log('add to cart clicked');
    e.preventDefault();
    var form_data = $(this).serializeArray();
    console.log(form_data);
    $.ajax({
        type: 'post',
        url: 'commerce/cart/updateCart',
        data: form_data,
        success: function(response) {
            if (response.success) {
                console.log('success');
                console.log(response.success);
                $(this).hide();
                $(this).siblings('.success').show();
                $(this).parents('.hover-cart').fadeOut();
            }
            else {
                console.log('error');
                console.log(response.success);
                alert("We're sorry, but the item couldn't be added to your cart. Please try again. If the issue persists, please send an email to webmaster@lwf.org");
            }
        }
    });        
});
up vote 2 down vote accepted

Controllers in Craft 3/Commerce 2 use kebab-case (update-cart) instead of camelCase (updateCate), so adjusting that may correct your issue.

The common convention for forms processed by Craft controllers is to leave the action attribute blank and include a hidden input with the action URL value.

In your example, you can do that by adding an action param to your form_data variable

var form_data = $(this).serializeArray();
// Add the action URL to the submitted data
form_data['action'] = 'commerce/cart/update-cart'

Then you'd leave the url param on your Ajax request blank. The updated code would look something like this if you add the action in your script.

$('.add-to-cart').on('submit', function(e) {
    console.log('add to cart clicked');
    e.preventDefault();
    var form_data = $(this).serializeArray();
    // Add the action URL to the submitted data
    form_data['action'] = 'commerce/cart/update-cart'
    console.log(form_data);
    $.ajax({
        type: 'post',
        url: '',
        data: form_data,
        dataType: 'json',
        success: function(response) {
            if (response.success) {
                console.log('success');
                console.log(response.success);
                $(this).hide();
                $(this).siblings('.success').show();
                $(this).parents('.hover-cart').fadeOut();
            }
            else {
                console.log('error');
                console.log(response.success);
                alert("We're sorry, but the item couldn't be added to your cart. Please try again. If the issue persists, please send an email to webmaster@lwf.org");
            }
        }
    });        
});

or the snippet below if you want to add the action to your Twig template

<form method="POST" class="add-to-cart">
    {{ csrfInput() }}
    {# Include the controller used to process the form  #}
    <input type="hidden" name="action" value="commerce/cart/update-cart">
    <input type="hidden" name="purchasableId" value="{{ variant.id }}">
    <input type="number" name="qty" value="1">
    <button type="submit"><i class="fas fa-shopping-cart"></i></button>
</form>

If you use the Twig code above, make sure you update the url property of your Ajax request to remove the existing URL.

  • This works much better! Thank you! I added the action to the script and updated to kebab-case. One issue I'm having trouble with is that it isn't running the success or error lines. It adds to the cart, console logs to just before the ajax statement, but doesnt run any of the hide or console logs below that. Should the success: function(response) { be different? I tried logging out the response but it gives me code errors anywhere I put it. – Indigo Viking Nov 2 at 20:19
  • Add dataType: 'json' to the Ajax arguments. Then the commerce controller will return JSON instead of redirecting as you're experiencing now. – Jeremy Daalder Nov 2 at 20:34
  • (code updated above) – Jeremy Daalder Nov 2 at 23:38

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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