discolabs / cartjs

A Javascript library to power cart management for Shopify themes.
https://cartjs.org
MIT License
478 stars 85 forks source link

How to show a message when customer orders more than current inventory quantity? #68

Open tsutshiau opened 8 years ago

tsutshiau commented 8 years ago

Hi, first of all, very, very thanks for your excellent plugin. Here's the question: I'm trying to display a message in order to prevent users from ordering more than current inventory quantity. But always failed (tried to output it as the max property of an input element, or just a data-* attribute of a span containing item.quantity). I think the problem is that I can't figure out how to output variant.inventory_quantity by using rivet.js...please help me!! Btw, can I comparing these two values in rv-show, to let rivet.js decide whether or not to display the message?

Uh, sorry that I'm not so familiar with JS so this might be a stupid question...Really thanks!

michaelrshannon commented 8 years ago

Part of the problem here is that the object that Shopify returns when you request the Cart via AJAX does not include all the properties for a variant - annoyingly, inventory_quantity is one of those missing properties.

@gavinballard This is a problem that we had to solve on our current project as the client really wanted to provide useful feedback to the user as they add items to the cart up to the current inventory limit, but it involved making Shopify.getProduct requests for each item in the cart every time it changes - due to other complexities we solved this outside of CartJS, but would be interested to know your thoughts on building something into CartJS that would retrieve extra Product/Variant properties whenever the cart changed...

gavinballard commented 8 years ago

Thanks @tsutshiau!

As @michaelrshannon said, it's a bit tricky to render inventory_quantity from Rivets as it's not something returned by the Ajax API. Two things that could help:

1) Use the rivetsModels option (see here) when initialising Cart.js on your product page to pass a full JSON object containing the product data (which should include inventory quantities), like this:

<script type="text/javascript">
  CartJS.init({{ cart | json }}, {
    rivetsModels: {
      "product": {{ product | json }}
    }
  });
</script>

2) The next major update to Cart.js is going to contain much, much better paradigms for returning information and error messages to customers, so doing things like displaying out of stock error messages should be greatly simplified.

lmartins commented 7 years ago

@gavinballard Also looking for a solution to this, is this something the library has solved in the meantime or do I need to pursue something similar to what @michaelrshannon describes?

gavinballard commented 7 years ago

@lmartins No change in the released version of the library at the moment I'm afraid. Inventory quantities are officially no longer returned in the Ajax API so for this to work we need a pattern to provide levels via Liquid.

allanarmstrong commented 7 years ago

Because I'm using the data attribute method of adding items to the cart I've found it difficult to add callbacks to the addItem function so I came up with my own work around for an error when adding an item to the cart: I've added the following code to the request in CartJS.Queue

statusCode: {
  422: function(err) {
    if (CartJS.errorHandling.cartError) {
      CartJS.errorHandling.cartError(JSON.parse(err.responseText));
    }
  }
}

I've also added a place holder for CartJS.errorHandling in my own fork of cartjs which looks like this

CartJS.errorHandling = {
  cartError: function(error) { console.log("Error adding item to the cart: ", error.description) }
}

But of course this is modifiable in the actual Shopify theme files like product.liquid or theme.liquid after CartJS has be initialised.

gavinballard commented 7 years ago

Thanks for sharing @allanarmstrong! We definitely need a better error-handling story.

lmartins commented 7 years ago

Thank you so much for sharing @allanarmstrong, this was indeed helpful.

kyl-newton commented 7 years ago

Are there any plans to implement improved error handling when using data attributes or has this project gone stale?

gavinballard commented 7 years ago

@kyl-newton I would love to implement this (along with a raft of other improvements), but I have pretty much zero time to work on it at the moment. Happily accepting contributions from others.

iamkeir commented 6 years ago

Just for reference, I prefer the approach detailed in this gist rather than changing core - I use this if it is helpful to anyone:

$(document).ajaxComplete(function(event, jqxhr, settings) {
  if (settings.url == '/cart.js') {

    console.log('GET /cart.js complete');

  } else if (settings.url.indexOf('/cart/') !== -1) {

    if (settings.url == '/cart/add.js') { console.log('POST cart/add.js complete'); }
    if (settings.url == '/cart/update.js') { console.log('POST cart/update.js complete'); }
    if (settings.url == '/cart/change.js') { console.log('POST cart/change.js complete'); }
    if (settings.url == '/cart/clear.js') { console.log('POST cart/clear.js complete'); }

  } else { // NOT CART AJAX

  }
});

Would be great if in due course, Cart.js accommodates success/error status in callbacks. If I have a moment, I will surely PR this!