Add only 2 products to cart

Topic summary

A merchant wants to limit customers to adding only 2 units per product variant on the product page, with an error message for attempts to add more. The implementation must preserve existing functionality like the cart-drawer behavior.

Current Issue:
Attempts to modify product-form.js (including AI-generated code) have broken core features:

  • Variant selection stops working (price doesn’t update when switching variants)
  • Cart-drawer functionality is disrupted, redirecting to cart page instead

The merchant shared their latest code attempt, which successfully prevents adding more than 2 items but breaks variant switching.

Response:
A community member noted this is an advanced customization beyond forum scope and cautioned against relying solely on AI-generated code without the technical expertise to verify its accuracy. They recommended hiring a developer for proper implementation.

Status: Unresolved. The merchant needs professional development assistance to implement this feature without breaking existing theme functionality.

Summarized with AI on November 1. AI used: claude-sonnet-4-5-20250929.

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}&section_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?

Hi @CGroenhaug this is an advanced theme customization beyond the scope of the forums not even counting the rule against randomizely generated “AI” nonsense.

AI tools are great summarizes for knowledge YOU HAVE the experience in to identify fact from gibberish for fools.

Using it as the ONLY source for skills you don’t have is just time wasting slop for you and others it’s literally not worth even reading the code.

Merchants that want to get customizations done properly can contact me for services.
Contact info in forum signature.
ALWAYS please provide context, examples: store url, theme name, post url(s) , or any further detail in ALL correspondence.