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

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

<p>In your example, you can do that by adding an <code>action</code> param to your <code>form_data</code> variable</p>

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

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

<pre><code>$('.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");
            }
        }
    });        
});
</code></pre>

<p>or the snippet below if you want to add the action to your Twig template</p>

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

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

CC BY-SA 4.0
2018-11-02T20:19:33.850Z
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.
Chattervast
CC BY-SA 4.0
2018-11-02T20:34:47.780Z
Add `dataType: 'json'` to the Ajax arguments. Then the commerce controller will return JSON instead of redirecting as you're experiencing now.
Jeremy Daalder
CC BY-SA 4.0
2018-11-02T23:38:10.680Z
(code updated above)
Jeremy Daalder
CC BY-SA 4.0
2018-11-02T19:07:21.737Z
2018-11-02T23:37:54.713Z
2018-11-02T23:37:54.713Z
Stephen Bowling
<p>Trying to ajax add to cart but each submit returns a </p>

<pre><code>https://www.website.com/commerce/cart/updateCart 404 (Not Found)
</code></pre>

<p>I have this in my twig template:</p>

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

<p>And this as my javascript:</p>

<pre><code>$('.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");
            }
        }
    });        
});
</code></pre>

<plugin-craftcommerce><form><ajax>
Craft Commerce 2 Ajax Add to Cart
# Craft Commerce 2 Ajax Add to Cart

(Asked by: username_0 on 2018-11-02)

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() %}

    {% for image in book.productImages.limit(1).all() %}
    
        
        
            
            {% set variant = book.defaultVariant %}
            
                {{ csrfInput() }}
                
                
                
            
        
    
    {% endfor %}
    {{ book.title }}
    {{ book.defaultVariant.price|currency }}

{% 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");
            }
        }
    });        
});

**Tags:** plugin-craftcommerce, form, ajax


---

## 1 answers

### Answer by username_1 on 2018-11-02. Score: 3 | Accepted answer

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

    {{ csrfInput() }}
    {# Include the controller used to process the form  #}
    
    
    
    


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

> **Comments:**
> **username_0**: 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.  
> **username_2**: Add `dataType: 'json'` to the Ajax arguments. Then the commerce controller will return JSON instead of redirecting as you're experiencing now.  
> **username_2**: (code updated above)  

---

