Saltar al contenido
merge.uydevelopers

Carrito con JavaScript

El theme puede leer y cambiar el carrito sin recargar la página, con los mismos endpoints que el carrito AJAX de Shopify.

Todas las rutas son relativas a la tienda (mismo origen que el theme). Las que cambian el carrito son POST, aceptan JSON o formulario y solo responden a pedidos del mismo origen. La respuesta es JSON.

Leer el carrito

GET /cart.js devuelve el carrito con la forma del objeto cart: item_count, items, total_price (en unidades menores), requires_shipping, currency. En cada línea, image es la URL de la imagen.

const cart = await fetch('/cart.js').then((r) => r.json());
document.querySelector('[data-cart-count]').textContent = cart.item_count;

Las páginas de la tienda se sirven desde caché y llegan con el carrito vacío: el contador del encabezado se completa así, con /cart.js. Solo la página /cart trae el carrito real en Liquid.

Agregar

POST /cart/add.js con { id, quantity } o con varias líneas { items: [{ id, quantity }] }. id es el id de la variante. Responde la línea agregada (o { items: [...] }).

const res = await fetch('/cart/add.js', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ id: variantId, quantity: 1 }),
});
if (!res.ok) {
  const error = await res.json();
  alert(error.description); // "Elegí una variante.", "Ese producto ya no está disponible."…
}

Sin JavaScript, el {% form 'product' %} hace lo mismo con un formulario común y lleva al carrito.

Cambiar una línea

POST /cart/change.js con { id, quantity } (id de la variante, o line con la posición en el carrito empezando en 1). quantity: 0 saca la línea. Responde el carrito completo.

await fetch('/cart/change.js', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ line: 1, quantity: 3 }),
});

Varias líneas a la vez

POST /cart/update.js con { updates: { "<id de variante>": cantidad } }. En un formulario, updates[<id>]=2. Sin .js, el formulario vuelve al carrito (o va al checkout si el botón se llama checkout).

Vaciar

POST /cart/clear.js deja el carrito vacío y lo devuelve.

Refrescar secciones

Las respuestas de add.js, change.js y update.js pueden traer el HTML de secciones ya renderizado con el carrito nuevo, para reemplazarlas sin otro pedido: mandá sections con los ids (de una sección estática como header, o de templates/cart.json).

const res = await fetch('/cart/add.js', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ id: variantId, quantity: 1, sections: ['header', 'cart-drawer'] }),
});
const data = await res.json();
for (const [id, html] of Object.entries(data.sections)) {
  if (html) document.getElementById(`section-${id}`).outerHTML = html;
}

Una sección que no existe llega como null. Pedí solo las que tenés que refrescar: hay un tope de secciones por pedido.

Errores

Los errores tienen la forma de Shopify: { "status": 422, "message": "Cart Error", "description": "…" }, con description lista para mostrar.

Estado Cuándo
400 El pedido está mal armado.
403 El pedido no vino de la tienda (otro origen).
404 El producto ya no está disponible.
422 Falta la variante o no hay stock para esa cantidad.
429 Demasiados intentos seguidos: esperá antes de reintentar.

Checkout

El checkout (/checkout) es de la plataforma y no lo edita el theme: el botón del carrito tiene que llevar ahí, con un link o con update y un botón name="checkout".