Where you can achieve what your competitors can’t


Minimum & Maximum quantity rules in Shopify

This custom code is completely free to use, but please note it does not include 1-on-1 technical support. If you need a bespoke, done-for-you solution to customize your Shopify store, my team is here to help! Head to my channel homepage and use the link in the trailer to reach out.

{%- assign rule = product.metafields.custom.product_rule.value -%}

{%- if rule -%}
  {%- assign min_qty = rule.minimum | default: 1 -%}
  {%- assign max_qty = rule.maximum | default: 9999 -%}
  {%- assign step_qty = rule.increment | default: 1 -%}

  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const qtyInput = document.querySelector('input[name="quantity"]');
      const addBtn = document.querySelector('button[name="add"], input[name="add"]');
      
      if (!qtyInput || !addBtn) return; 

      const originalBtnText = addBtn.querySelector('span') ? addBtn.querySelector('span').innerText : addBtn.innerText;

      qtyInput.setAttribute('min', '{{ min_qty }}');
      qtyInput.setAttribute('max', '{{ max_qty }}');
      qtyInput.setAttribute('step', '{{ step_qty }}');
      
      if (parseInt(qtyInput.value) < {{ min_qty }}) {
        qtyInput.value = '{{ min_qty }}';
      }

      const validateQuantity = () => {
        const currentVal = parseInt(qtyInput.value);
        const min = {{ min_qty }};
        const max = {{ max_qty }};
        const step = {{ step_qty }};

        let isValid = true;
        let errorMessage = '';

        if (currentVal < min) {
          isValid = false;
          errorMessage = `Minimum is ${min}`;
        } else if (currentVal > max) {
          isValid = false;
          errorMessage = `Maximum is ${max}`;
        } else if (currentVal % step !== 0) {
          isValid = false;
          errorMessage = `Must be multiples of ${step}`;
        }

        if (!isValid) {
          addBtn.disabled = true;
          if (addBtn.querySelector('span')) {
            addBtn.querySelector('span').innerText = errorMessage;
          } else {
            addBtn.innerText = errorMessage;
          }
        } else {
          addBtn.disabled = false;
          if (addBtn.querySelector('span')) {
            addBtn.querySelector('span').innerText = originalBtnText;
          } else {
            addBtn.innerText = originalBtnText;
          }
        }
      };

      qtyInput.addEventListener('input', validateQuantity);
      qtyInput.addEventListener('change', validateQuantity);

      validateQuantity();
    });
  </script>
{%- endif -%}