Hi! We want to implement so that when you are on the product page you can only add 2 of each variant to the shopping cart. If you try to add more than that you get a message. When I do this it is important that functionality such as updating the cart-drawer is not broken.
I have tried to do this with chatgpt, but then either choosing different variants is broken, or you end up on the cart page and not in the cart-drawer when adding products. Then we have worked with product-form.js
This is the latest proposal:
if (!customElements.get(‘product-form’)) {
customElements.define(
‘product-form’,
class ProductForm extends HTMLElement {
constructor() {
super();
this.form = this.querySelector(‘form’);
this.variantIdInput.disabled = false;
this.form.addEventListener(‘submit’, this.onSubmitHandler.bind(this));
this.cart = document.querySelector(‘cart-notification’) || document.querySelector(‘cart-drawer’);
this.submitButton = this.querySelector(‘[type=“submit”]’);
this.submitButtonText = this.submitButton.querySelector(‘span’);
if (document.querySelector(‘cart-drawer’)) {
this.submitButton.setAttribute(‘aria-haspopup’, ‘dialog’);
}
this.hideErrors = this.dataset.hideErrors === ‘true’;
// Legg til event listener for variantendring
this.form.addEventListener(‘change’, this.onVariantChange.bind(this));
}
/**
- Håndter innsending av skjema
*/
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);
try {
const cartState = await this.getCartState();
const variantId = formData.get(‘id’);
const quantity = parseInt(formData.get(‘quantity’), 10) || 1;
const existingItem = cartState.items.find((item) => item.variant_id == variantId);
// Valider maks 2 produkter per variant
if (existingItem && existingItem.quantity + quantity > 2) {
this.handleErrorMessage(
‘Du kan kun legge til 2 stk av hver variant. Ønsker du å handle flere ta kontakt med oss.’
);
return;
}
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;
const response = await fetch(${routes.cart_add_url}, config);
const data = await response.json();
if (data.status) {
this.handleErrorMessage(data.description || data.message);
return;
}
if (this.cart) {
this.cart.renderContents(data);
}
} catch (error) {
console.error(error);
this.handleErrorMessage(‘En feil oppstod. Prøv igjen senere.’);
} 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’);
}
}
/**
- Håndter variantendring: Oppdater variant-ID og pris
*/
async onVariantChange() {
try {
const variantId = this.variantIdInput.value;
// Hent oppdatert produktinformasjon
const response = await fetch(/products/${this.dataset.handle}?variant=${variantId}§ion_id=main-product);
if (!response.ok) throw new Error(‘Kunne ikke hente variantinformasjon.’);
const html = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(html, ‘text/html’);
// Oppdater pris
const newPrice = doc.querySelector(‘.product-price’);
if (newPrice) {
const priceContainer = this.querySelector(‘.product-price’);
if (priceContainer) {
priceContainer.innerHTML = newPrice.innerHTML;
}
}
// Fjern feilmeldinger ved suksess
this.handleErrorMessage();
} catch (error) {
console.error(‘Feil ved variantendring:’, error);
this.handleErrorMessage(‘Kunne ikke oppdatere varianten. Prøv igjen.’);
}
}
/**
- Hent handlekurvens tilstand
*/
async getCartState() {
const response = await fetch(${routes.cart_url}.js, {
headers: { ‘X-Requested-With’: ‘XMLHttpRequest’ },
});
if (!response.ok) throw new Error(‘Kunne ikke hente handlekurvens tilstand.’);
return response.json();
}
/**
- Håndter feilmeldinger
*/
handleErrorMessage(errorMessage = false) {
if (this.hideErrors) return;
this.errorMessageWrapper =
this.errorMessageWrapper || this.querySelector(‘.product-form__error-message-wrapper’);
if (!this.errorMessageWrapper) return;
this.errorMessage = this.errorMessage || this.errorMessageWrapper.querySelector(‘.product-form__error-message’);
this.errorMessageWrapper.toggleAttribute(‘hidden’, !errorMessage);
if (errorMessage) {
this.errorMessage.textContent = errorMessage;
}
}
/**
- Variant-ID getter
*/
get variantIdInput() {
return this.form.querySelector(‘[name=id]’);
}
}
);
}
But here the selection of variants stops working.
So when you click between the variants the price does not change.
Anyone have a suggestion?