You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shopify中自定义尺寸与尺寸变体的互斥选择实现问询

解决方案:实现尺寸变体与自定义尺寸的互斥提交

核心思路

  • 跟踪用户选择的模式(变体尺寸/自定义尺寸)
  • 在表单提交前动态调整表单字段:
    • 变体模式:清空自定义尺寸字段值,确保变体ID正常提交
    • 自定义尺寸模式:临时移除变体选择器的提交属性,确保自定义属性提交,同时可搭配专门的“自定义”变体管理库存

步骤1:优化HTML结构

给变体选择器添加专属类,方便后续JS操作:

<div class="select">
  <!-- 添加variant-size-select类用于快速定位 -->
  <select id="product-select-{{ product.id }}{{ product-form }}{{ section.id }}{{ block.id }}" 
          name="id" 
          class="multi_select variant-size-select" 
          data-variants>
    {% for v in product.variants %}
      <option {% if v == variant %}selected="selected"{% endif %} 
              value="{{ v.id }}" 
              data-featured-image="{{ v.featured_media }}" 
              data-image="{{ v.featured_media | product_img_url: '600x' }}" 
              data-sku="{{ v.sku }}">{{ v.title }}</option>
    {% endfor %}
  </select>
  {% if product.tags contains 'Custom Size' %}
    <div>
      <div class='toggle-customizable-wrapper'>
        Or
        <button type="button" id="toggle-custom-size">Custom Size</button>
      </div>
      <div id="custom-size-fields" style="display:none; margin-top: 10px;">    
        <label for="unit-of-measure">Unit of Measure:</label>
        <select id="unit-of-measure" class="custom-size-input" name="properties[Unit of Measure]">
          <option value="cm">Cm</option>
          <option value="ft">Ft</option>
        </select>
        <p>
          Selected size: <span class="chosen-size">0 x 0</span> <span class="chosen-unit">Cm</span>
        </p>
        <div class='product-custom-size-container'>
          <div>
            <label for="custom-width">Width:</label>
            <input type="number" value='0' id="custom-width" class="custom-size-input" name="properties[Custom Width]" min="1"  placeholder="Enter width">
          </div>
          <div>
            <label for="custom-length">Length:</label>
            <input type="number" value='0' id="custom-length" class="custom-size-input" name="properties[Custom Length]" min="1"  placeholder="Enter length">
          </div>
          <div class="chosen-unit-container">
            <p class="chosen-unit">Cm</p>        
          </div>
        </div>
      </div>
    </div>
  {% endif %}
</div>

步骤2:完整JavaScript实现

替换原有Script,实现模式切换、字段状态管理和表单提交逻辑:

document.addEventListener("DOMContentLoaded", function() {
  // 获取核心元素
  const toggleCustomBtn = document.getElementById('toggle-custom-size');
  const customSizeFields = document.getElementById('custom-size-fields');
  const variantSelect = document.querySelector('.variant-size-select');
  const customInputs = document.querySelectorAll('.custom-size-input');
  const productForm = document.getElementById('product_form_{{ product.id }}');
  const widthInput = document.getElementById('custom-width');
  const lengthInput = document.getElementById('custom-length');
  const unitSelect = document.getElementById('unit-of-measure');
  const chosenSizeSpan = document.querySelector('.chosen-size');
  const chosenUnitSpans = document.querySelectorAll('.chosen-unit');
  
  // 状态标记:是否启用自定义尺寸模式
  let isCustomMode = false;

  // 切换自定义尺寸面板
  toggleCustomBtn.addEventListener('click', function() {
    isCustomMode = !isCustomMode;
    customSizeFields.style.display = isCustomMode ? 'block' : 'none';
    
    // 模式切换时重置对应字段
    if (isCustomMode) {
      // 自定义模式:禁用变体选择器,清空自定义字段默认值
      variantSelect.disabled = true;
      widthInput.value = '';
      lengthInput.value = '';
    } else {
      // 变体模式:启用变体选择器,清空所有自定义属性值
      variantSelect.disabled = false;
      customInputs.forEach(input => {
        if (input.type === 'text' || input.type === 'number') input.value = '';
        else if (input.tagName === 'SELECT') input.selectedIndex = 0;
      });
      updateChosenSize();
    }
  });

  // 更新自定义尺寸预览文本
  function updateChosenSize() {
    const width = widthInput.value || '0';
    const length = lengthInput.value || '0';
    const unit = unitSelect.value;
    chosenSizeSpan.textContent = `${width} x ${length}`;
    chosenUnitSpans.forEach(span => span.textContent = unit.toUpperCase());
  }

  // 监听自定义尺寸输入变化
  widthInput.addEventListener('input', updateChosenSize);
  lengthInput.addEventListener('input', updateChosenSize);
  unitSelect.addEventListener('change', updateChosenSize);

  // 处理表单提交,确保互斥逻辑生效
  productForm.addEventListener('submit', function(event) {
    if (isCustomMode) {
      // 自定义模式:临时移除变体选择器的name属性,避免提交变体ID
      const originalName = variantSelect.name;
      variantSelect.name = '';
      
      // 可选:验证自定义尺寸是否填写完整
      if (!widthInput.value || !lengthInput.value) {
        event.preventDefault();
        alert('Please enter both width and length for custom size.');
        variantSelect.name = originalName;
        return;
      }
      
      // 提交后恢复name属性,避免后续操作异常
      setTimeout(() => variantSelect.name = originalName, 100);
    } else {
      // 变体模式:清空所有自定义属性字段值,避免多余数据提交
      customInputs.forEach(input => {
        if (input.type === 'text' || input.type === 'number') input.value = '';
      });
    }
  });
});

关键说明

  1. 字段动态调整:自定义模式下临时移除变体选择器的name属性,确保表单不提交变体ID;变体模式下清空自定义字段值,避免多余属性进入购物车。
  2. 状态同步:切换模式时自动重置对应字段,防止用户残留输入导致逻辑混乱。
  3. 兼容主题逻辑:无需完全拦截表单提交,仅在提交前调整字段状态,兼容主题自带的Ajax加购功能。

额外建议

  • 在产品后台创建专门的“Custom Size”变体,自定义模式下默认选中该变体,便于库存管理。
  • 若主题使用了第三方加购脚本,确保上述代码在主题脚本之后加载,避免事件冲突。

内容的提问来源于stack exchange,提问作者youssef ACHCHIRAJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 18:55:12