Liquid Ajax Cart re-renders cart HTML after each user action, such as adding a product to the cart or changing cart item quantity. It uses Shopify Bundled section rendering under the hood, so the cart content must be a Shopify section.
Create a new Shopify section that works without Ajax. Use any Liquid objects, tags and filters. Styling is up to you as well.
<div class="my-cart">
<h2>Cart ({{ cart.item_count }})</h2>
<div class="my-cart__items">
<!-- Loop through cart items -->
{% for line_item in cart.items %}
{% assign line_item_index = forloop.index %}
<div><a href="{{ line_item.url }}">{{ line_item.title | escape }}</a></div>
<div>Price: {{ line_item.final_price | money }}</div>
<div>
Quantity:
<!-- "Minus one" button -->
<a href="{{ routes.cart_change_url }}?line={{ line_item_index }}&quantity={{ line_item.quantity | minus: 1 }}" >
Minus one
</a>
<!-- Item quantity input -->
<input
name="updates[]"
value="{{ line_item.quantity }}"
type="number"
form="my-ajax-cart-form" />
<!-- "Plus one" button -->
<a href="{{ routes.cart_change_url }}?line={{ line_item_index }}&quantity={{ line_item.quantity | plus: 1 }}">
Plus one
</a>
</div>
<div>Total: <strong>{{ line_item.final_line_price | money }}</strong></div>
<!-- "Remove item" button -->
<a href="{{ line_item.url_to_remove }}">
Remove
</a>
<hr/>
{% endfor %}
</div>
{% form 'cart', cart, id: 'my-ajax-cart-form' %}
<button type="submit" name="checkout">
Checkout — {{ cart.total_price | money_with_currency }}
</button>
{% endform %}
</div>
{% schema %} { "name": "My Ajax cart" } {% endschema %}
Include the section to the layout/theme.liquid
where you want to show the Ajax cart.
{% section 'my-ajax-cart' %}
The section will appear on the page. The “Plus”, “Minus”, “Remove” button clicks will update the cart, but still with the page refresh.
Use HTML attributes and custom tags to mark elements that should be ajaxified.
Add the data-ajax-cart-section
attribute to an element
whose content should be re-rendered after each user action, such as adding a product to the cart or changing cart item quantity.
In our case we want to enable re-rendering for the whole section content, so add the attribute to the root element —
the one with the my-cart
CSS class.
If you have an area with a scrollbar, add the data-ajax-cart-section-scroll
attribute to it —
Liquid Ajax Cart will keep the scroll position unchanged while re-rendering.
Add the data-ajax-cart-quantity-input
attribute to the cart item quantity input.
When a user changes the input value, Liquid Ajax Cart initiates a Shopify Cart API “change quantity” request
and re-render the data-ajax-cart-section
containers.
To bind the “Plus” and “Minus” buttons to the cart item quantity input,
wrap them all in the <ajax-cart-quantity>
tag
and add the attributes data-ajax-cart-quantity-plus
and data-ajax-cart-quantity-minus
to the buttons.
When a user clicks the button, Liquid Ajax Cart updates the input value,
initiates a Shopify Cart API “change quantity” request
and re-renders the data-ajax-cart-section
containers.
Add the data-ajax-cart-request-button
attribute to the “Remove item” button —
the one with the href="{{ line_item.url_to_remove }}"
attribute.
When a user clicks a link with the data-ajax-cart-request-button
attribute,
Liquid Ajax Cart initiates a Shopify Cart API Ajax request based on the URL from the href
parameter
and re-renders the data-ajax-cart-section
containers
if the request is successful.
Check out all the supported URLs on the data-ajax-cart-request-button
page.
To display error messages, such as when a user attempts to add more items to the cart than are available in stock,
add an element with the data-ajax-cart-errors
attribute and set the value to the corresponding cart item key.
When Shopify returns an error message in response to an Ajax request related to a cart item, Liquid Ajax Cart searches for the element designated for the cart item error messages and inserts the error message into that element.
<div class="my-cart" data-ajax-cart-section>
<h2>Cart ({{ cart.item_count }})</h2>
<div class="my-cart__items" data-ajax-cart-section-scroll>
<!-- Loop through cart items -->
{% for line_item in cart.items %}
{% assign line_item_index = forloop.index %}
<div><a href="{{ line_item.url }}">{{ line_item.title | escape }}</a></div>
<div>Price: {{ line_item.final_price | money }}</div>
<div>
Quantity:
<ajax-cart-quantity>
<!-- "Minus one" button -->
<a data-ajax-cart-quantity-minus
href="{{ routes.cart_change_url }}?line={{ line_item_index }}&quantity={{ line_item.quantity | minus: 1 }}" >
Minus one
</a>
<!-- Item quantity input -->
<input data-ajax-cart-quantity-input="{{ line_item_index }}"
name="updates[]"
value="{{ line_item.quantity }}"
type="number"
form="my-ajax-cart-form" />
<!-- "Plus one" button -->
<a data-ajax-cart-quantity-plus
href="{{ routes.cart_change_url }}?line={{ line_item_index }}&quantity={{ line_item.quantity | plus: 1 }}">
Plus one
</a>
</ajax-cart-quantity>
</div>
<!-- Item error messages -->
<div data-ajax-cart-errors="{{ line_item.key }}"></div>
<div>Total: <strong>{{ line_item.final_line_price | money }}</strong></div>
<!-- "Remove item" button -->
<a data-ajax-cart-request-button href="{{ line_item.url_to_remove }}">
Remove
</a>
<hr/>
{% endfor %}
</div>
{% form 'cart', cart, id: 'my-ajax-cart-form' %}
<button type="submit" name="checkout">
Checkout — {{ cart.total_price | money_with_currency }}
</button>
{% endform %}
</div>
{% schema %} { "name": "My Ajax cart" } {% endschema %}
Add the data-ajax-cart-property-input
to a cart note field,
a cart item property field, or a cart attribute field to ajaxify them.
When a user changes the field value, Liquid Ajax Cart sends a Shopify Cart API request to update the value
and re-renders the data-ajax-cart-section
containers.
The data-ajax-cart-property-input
attribute supports text inputs, checkboxes, radio buttons, the tags select
and textarea
.
Explore examples for all the features on the data-ajax-cart-property-input
page.
<div class="my-cart" data-ajax-cart-section>
<h2>Cart ({{ cart.item_count }})</h2>
<div class="my-cart__items" data-ajax-cart-section-scroll>
<!-- Cart items code -->
</div>
<textarea data-ajax-cart-property-input
name="note"
form="my-ajax-cart-form">
{{ cart.note }}
</textarea>
{% form 'cart', cart, id: 'my-ajax-cart-form' %}
<button type="submit" name="checkout">
Checkout — {{ cart.total_price | money_with_currency }}
</button>
{% endform %}
</div>
{% schema %} { "name": "My Ajax cart" } {% endschema %}
When Liquid Ajax Cart initiates an Ajax request, it appends the js-ajax-cart-processing
CSS class to the html
tag.
Use this class to signify that the cart is being updated.
.my-cart__items {
opacity: 1;
transition: opacity .2s;
}
/* Make the cart content look visually disabled while updating */
html.js-ajax-cart-processing .my-cart__items {
opacity: .7;
}
/* Show a loading indicator */
html.js-ajax-cart-processing .my-cart__items:before {
content: 'Loading';
display: block;
}
During the re-rendering process, Liquid Ajax Cart replaces all the HTML within the data-ajax-cart-section
element with new content.
If you have third-party scripts or applications injecting their HTML into the cart section, preserving these modifications during re-rendering is crucial.
To keep a specific area within the data-ajax-cart-section
element unchanged, add the data-ajax-cart-static-element
attribute
to the parent element of the area. Liquid Ajax Cart will maintain the inner HTML of this area unchanged while updating the surrounding HTML.
<div class="my-cart" data-ajax-cart-section>
<h2>Cart</h2>
<div class="my-cart__items">
<!-- Cart items HTML -->
</div>
<div data-ajax-cart-static-element class="my-cart__third-party-upsell-app-wrapper">
<!-- Liquid Ajax Cart will never change the HTML within data-ajax-cart-static-element -->
</div>
{% form 'cart', cart, id: 'my-ajax-cart-form' %}
<button type="submit" name="checkout">
Checkout — {{ cart.total_price | money_with_currency }}
</button>
{% endform %}
</div>
{% schema %} { "name": "My Ajax cart" } {% endschema %}
Liquid Ajax Cart replaces the HTML content of data-ajax-cart-section
containers after a successful Shopify Cart API Ajax request.
To execute your JavaScript code after this replacement occurs,
you should subscribe to the liquid-ajax-cart:request-end
event:
document.addEventListener("liquid-ajax-cart:request-end", function(event) {
const {sections} = event.detail;
console.log("Sections are re-rendered: ", sections);
});
The detailed explanation on how to interact with Liquid Ajax Cart using JavaScript is in the “Lifecycle, events, API” guide.