I created a snippet that adds some buttons to the product page and allows the customer to add to cart. Initially, I was using a slide cart app, and it works fine . I am trying to switch to using the Dawn Theme built in slide cart, but I do not know how to force the cart to refresh & slide open when items are added.
In the addToCart function below, the following 2 lines work with the app’s slide cart and update then slide it open accordingly. I am looking to do this with the Dawn Theme slide cart. Is this achievable?
this.window.SLIDECART_UPDATE(response);
this.window.SLIDECART_OPEN();
addToCart function:
function addToCart(product_formData) {
let formData = product_formData;
fetch(window.Shopify.routes.root + 'cart/add.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then((response) => response.json())
.then((response) => {
this.window.SLIDECART_UPDATE(response);
this.window.SLIDECART_OPEN();
})
.catch((e) => {
console.error(e);
});
AMaL
December 21, 2024, 7:19pm
2
Would you like to activate the cart drawer in your store?
The cart drawer is already activated in my store. This is a custom add to cart button that I am working with, and when the items are added to the cart I want the slide cart to update and open. As of now, it does not update the slide cart until page refresh.
AMaL
December 21, 2024, 9:09pm
5
"I’ve checked the code you provided, and it’s working fine for me. I’ve added the button in the buy-buttons.liquid
file. When I click the button, the item is added to the cart and the cart drawer opens.
<button id="additional_button" onclick="addToCart()" type="submit" class="product-form__submit button button--full-width button--primary">
Additional Button
</button>
<script>
function addToCart() {
let formData = product - form;
fetch(window.Shopify.routes.root + 'cart/add.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
})
.then((response) => response.json())
.then((response) => {
this.window.SLIDECART_UPDATE(response);
this.window.SLIDECART_OPEN();
})
.catch((e) => {
console.error(e);
});
}
</script>
If you add it to the buy-buttons.liquid
file, it is not actually using the addToCart function it is just doing the same thing that the regular buy button does. If you removed the addToCart script or the onClick in your code, it would still do the same thing I believe.
AMaL
December 22, 2024, 7:24am
7
I have created a file in the snippets folder named additional-buttons.liquid and added the below code.
<div>
<product-form
class="product-form"
id="product-form-{{ product_form_id }}"
>
{%- form 'product', product, id: product_form_id, class: 'form', novalidate: 'novalidate' -%}
<input
type="hidden"
name="id"
value="{{ product.selected_or_first_available_variant.id }}"
{% if product.selected_or_first_available_variant.available == false
or quantity_rule_soldout
or product.selected_or_first_available_variant == null
%}
disabled
{% endif %}
class="product-variant-id"
>
<button
id="additional_button"
type="submit"
class="product-form__submit button button--full-width button--primary"
>
Additional Button
</button>
{%- render 'loading-spinner' -%}
{%- endform -%}
</product-form>
</div>
In the main-product.liquid file, I have added the snippet below the buy-buttons .
{%- render 'additional-buttons',
block: block,
product: product,
product_form_id: product_form_id,
section_id: section.id,
show_pickup_availability: true
-%}
The code add the product to the cart and open the drawer.
Oh, I see. Is there a way to adjust your code so that it adds 3 items to the cart? On my page I have 2 checkbox upsells (image below):
My goal with this is if both checkboxes are selected when the user clicks the ATC button, all 3 items are added to the cart, and the cart drawer opens. If only 1 checkbox is checked, it adds that upsell and the main product to the cart, etc…
My current implementation achieves this but it does not cause the cart to visually update until page reload. My implementation does not utilize a form though, it just makes a post request when the button is clicked. Can your code be edited to add 3 items to cart at the same time?
Thank you for taking the time to help me. I appreciate it.
AMaL
December 24, 2024, 3:20am
9
Could you please try the code below?
Create a new file snippets/additional-buttons.liquid
<input
type="checkbox"
id="upsell-checkbox-1"
name="upsell-1"
value="true"
data-variant-id={{ data-variant-id }}
data-product-id={{ data-product-id }}
section-id={{ section_id }}
>
<label for="upsell-checkbox-1"> The Multi-managed Snowboard </label>
snippets/buy-buttons.liquid
{%- render 'additional-buttons',
data-variant-id: "42143107678268",
data-product-id: "7775528878140",
section_id: section.id
-%}
Currently, I have hardcoded the add-on product ID and placed the snippet above the <product-form>
tag.
assets/product-form.js
Please update the onSubmitHandler(evt)
in the product-form.js
file with the code below.
async onSubmitHandler(evt) {
evt.preventDefault();
if (this.submitButton.getAttribute('aria-disabled') === 'true') return;
this.handleErrorMessage();
this.submitButton.setAttribute('aria-disabled', true);
this.submitButton.classList.add('loading');
this.querySelector('.loading__spinner').classList.remove('hidden');
const config = fetchConfig('javascript');
config.headers['X-Requested-With'] = 'XMLHttpRequest';
delete config.headers['Content-Type'];
const formData = new FormData(this.form);
if (this.cart) {
formData.append(
'sections',
this.cart.getSectionsToRender().map((section) => section.id),
);
formData.append('sections_url', window.location.pathname);
this.cart.setActiveElement(document.activeElement);
}
config.body = formData;
let data = {};
try {
const response = await fetch(`${routes.cart_add_url}`, config);
data = await response.json();
if (data.status) {
publish(PUB_SUB_EVENTS.cartError, {
source: 'product-form',
productVariantId: formData.get('id'),
errors: data.errors || data.description,
message: data.message,
});
this.handleErrorMessage(data.description);
const soldOutMessage =
this.submitButton.querySelector('.sold-out-message');
if (!soldOutMessage) return;
this.submitButton.setAttribute('aria-disabled', true);
this.submitButtonText.classList.add('hidden');
soldOutMessage.classList.remove('hidden');
this.error = true;
return;
} else if (!this.cart) {
window.location = window.routes.cart_url;
return;
}
if (!this.error) {
publish(PUB_SUB_EVENTS.cartUpdate, {
source: 'product-form',
productVariantId: formData.get('id'),
cartData: data,
});
}
const upsellCheckbox = document.getElementById('upsell-checkbox-1');
const upsellProductId = upsellCheckbox.getAttribute('data-product-id');
const upsellVariantId = upsellCheckbox.getAttribute('data-variant-id');
const sectionId = upsellCheckbox.getAttribute('section-id');
const quantityElement = document.getElementById('Quantity-template--17232286384188__main');
const quantityValue = quantityElement ? quantityElement.value : 1;
if (upsellCheckbox.checked) {
formData.append('id', upsellVariantId);
formData.append('quantity', quantityValue);
formData.append('product-id', upsellProductId);
config.body = formData;
const upsellResponse = await fetch(`${routes.cart_add_url}`, config);
data = await upsellResponse.json();
}
this.error = false;
const quickAddModal = this.closest('quick-add-modal');
if (quickAddModal) {
document.body.addEventListener(
'modalClosed',
() => {
setTimeout(() => {
this.cart.renderContents(data);
});
},
{ once: true },
);
quickAddModal.hide(true);
} else {
this.cart.renderContents(data);
}
} catch (e) {
console.error(e);
} finally {
this.submitButton.classList.remove('loading');
if (this.cart && this.cart.classList.contains('is-empty')) {
this.cart.classList.remove('is-empty');
}
if (!this.error) this.submitButton.removeAttribute('aria-disabled');
this.querySelector('.loading__spinner').classList.add('hidden');
}
}