【问题标题】:Related products by variant using metafields for Shopify Liquid使用 Shopify Liquid 的元字段按变体分类的相关产品
【发布时间】:2016-05-16 00:14:25
【问题描述】:

我正在尝试在 Caroline 的相关产品解决方案的基础上构建具有元字段的相关产品变体。即,当您单击桌子的白色变体时,您将看到椅子的白色变体作为相关产品。 (与将桌面产品链接到椅子产品而不管变体如何。)Caroline 的解决方案在这里:https://gist.github.com/carolineschnapp/1003334 以下是我的代码。现在,它在页面加载时将相同的产品置于两次,并且在选择不同的借用时,没有任何反应。我为每个变体格式化元字段值的方式是放置“related-product-handle-1,variant-id-1,related-product-handle-2,variant-id-2,related-product-handle-3 , variant-id-3" 而不仅仅是产品句柄。

{% assign image_size = 'compact' %}
{% assign heading = 'Related Products' %}

{% if product.selected_or_first_available_variant.metafields.recommendations.productHandles %}

<h3>{{ heading }}</h3>
<ul class="related-products"></ul>

{% endif %}

<script>!window.jQuery && document.write('<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"><\/script>')</script>
{{ 'api.jquery.js' | shopify_asset_url | script_tag }}

<script type="text/javascript" charset="utf-8">  

$(document).ready(function(){

setTimeout(function() {
    var dd = $('.single-option-selector#product-select-option-0');
      var vId = location.search.substring(9);
      switchRelated(vId);

    dd.on('change', function() {
      $('ul.related-products').empty();
      var vId = location.search.substring(9);
      switchRelated(vId);  
    });

    function switchRelated(vId) {
      var list = $('ul.related-products');
      var vIdd = parseInt(vId);
      {% for variant in product.variants %}
        {% if variantId == vIdd %}
          {% if variant.metafields.recommendations.productHandles %}
            recommendations = jQuery.trim({{ variant.metafields.recommendations.productHandles | json }}).split(/[\s,;]+/);
            for (var i=0; i < (recommendations.length); i+=2 ) {
              var j = (i + 1);
              if (recommendations.length && recommendations[i] && recommendations[j] !== '') {
                jQuery.getJSON('/products/' + recommendations[i] + '.js', function(product) {
                  product.variants.forEach(function(variant) {
                    if (variant.id == parseInt(recommendations[j])) {
                      list.append('<li><div class="image"><a href="' + product.url + '?variant=' + recommendations[j] +'"><img src="' + variant.featured_image.src + '" /></a></div><h4><a href="' + product.url + '?variant=' + recommendations[j] + '">' + product.title + '</a></h4></li>'); 
                    }
                  });
                });
              }
            } 
          {% endif %}   
        {% endif %}
      {% endfor %}
    }    
  }, 1);
});
</script>

答案已编辑:第一个非常有用,一旦我对语法错误进行了一些更正和一些简短的补充。这是我为可能需要的任何人提供的答案的编辑版本:

产品.液体:

 {% for variant in product.variants %}
                {% capture metafield_data %}{% endcapture %}
                {% assign related_products = variant.metafields.recommendations.productHandles | split: '|' %}
                {% for related_product in related_products %}
                  {% assign metafield_items = related_product | split: ',' %}
                  {% assign r_p = metafield_items[0] %}
                  {% assign r_v = metafield_items[1] | plus: 0 %} 
                  {% assign r_n = all_products[r_p].title %}
                  {% for related_variant in all_products[r_p].variants %}
                    {% if related_variant.id == r_v %} 
                      {% assign r_i = related_variant.image.src | img_url: 'small' %}
                    {% endif %}
                  {% endfor %}
                  {% capture metafield_data %}{{metafield_data}}{{ r_p }},{{ r_v }},{{ r_i }},{{ r_n }}{% unless forloop.last %}|{% endunless %}{% endcapture %}
                {% endfor %}
                <option id="{{ variant.id }}" data-metafield="{{ metafield_data }}" {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}- {{ related_products.size }}</option>
              {% endfor %}

以及相关的变体 javascript sn-p:

$(document).ready(function(){

  setTimeout(function() {
    var dd = $('.single-option-selector#product-select-option-0');
    if(location.search.substring(9) != ''){
      var vId = location.search.substring(9);
     }
     else {
      var vId = {{ product.selected_or_first_available_variant.id }};
     }
    switchRelated(vId);


    $('#product-select option').each(function(index, element){

      $(".single-option-selector#product-select-option-0 option:eq(" + index + ")").attr('id', element.id);
      $('.single-option-selector#product-select-option-0 option:eq(' + index + ')').attr('data-metafield', $(element).attr("data-metafield"));
      $('#product-select option:eq(' + index + ')').attr('id', '');


    });


    dd.on('change', function() {
      var list = $('ul.related-products');
      $(list).children().remove();
       $(list).empty();
      if(location.search.substring(9) != ''){
        var vId = location.search.substring(9);
      }
      else {
       var vId = {{ product.selected_or_first_available_variant.id }};
      }
      switchRelated(vId);  
    });

    function switchRelated(vId) {
      var list = $('ul.related-products');
      $(list).children().remove();
      $(list).empty();
      var vIdd = parseInt(vId);

      console.log(vIdd)
      var variant_matches = $('#' + vId).attr('data-metafield').split('|');

      for (var i=0; i < variant_matches.length; i++) {
          var items = variant_matches[i].split(','); 

          list.append('<li><div class="image"><a href="/products/'+items[0]+'/?variant='+items[1]+'"><img src="'+items[2]+'" /></a></div><h4><a href="/products/' + items[0] + '?variant=' + items[2] + '">' + items[3].replace('_','') + '</a></h4></li>');

      }
    }   
  }, 1);
});

我唯一担心的是我正在将数据从“产品选择”下拉列表复制到“单选项选择器”下拉列表中。我这样做是因为没有用于呈现单选项选择器的模板,它似乎是通过 javascript 添加的。如果有人对在液体中操纵单选项选择器有任何见解,请告诉我。谢谢!!

【问题讨论】:

  • 这是一个很好的问题,你有我的支持。但是代码中的{% if variantId == vIdd %} 是什么?您是否尝试使用液体变量验证 JS 变量?
  • @HymnZ 我使用 location.search (vId) 从 url 传入变量参数,而 vIdd 是 vId 的解析整数形式。由于我无法通过变体 ID 直接查询 Product 对象,因此我正在遍历 product.variants 并捕获与 url 具有相同 ID 的变体,即当前选择的变体。 (我不使用液体的“selected_or_first_available_variant”对象的原因是因为当用户从下拉列表中选择新变体时,它没有捕获正确的变体 ID。
  • 尽管如此,您不能将 JavaScript 变量传递给流动代码。由于您这样做,整个 JavaScript 仅加载首先从服务器端生成的值(液体值),因此后续更改不会影响。你的函数在这里中断{% if variantId == vIdd %}。检查控制台日志。如果您可以使用适当的元字段值样本更新您的问题,我可以提供答案。
  • 我确实检查控制台日志@hymnz 关键 productHandles 的元字段值的示例是:classic-chair, 18273486, modern-chair, 15438726, wood-chair, 19484672

标签: javascript jquery shopify liquid


【解决方案1】:

实现这一点的最快方法是让 Shopify 服务器构建元素,以使用任何 AJAX 调用来拉取链接和图像 URL。以下是操作方法。

从您的 productHandles 示例中,我猜测列表中的 3 项与特定变体 id xxxxxx 相关。以这种方式构造元字段值

rph-1,rph-v-id-1|rph-2,rph-v-id-2|rph-3,rph-v-id-3

现在在产品液体中找到这个部分

&lt;select class="product-select" id="product-select" name="id" .... &lt;/select&gt;

把里面的html改成下面的——

{% for variant in product.variants %}
    {% assign related_products = variant.metafields.recommendations.productHandles | split: '|' %}
    {% for related_product in related_products %}
      {% assign metafield_items = related_product | split: ',' %}
      {% assign r_p = metafield_items[0] %}
      {% assign r_v = metafield_items[1] | plus: 0 %} {% comment %} converting string to number {% endcomment %}
      {% assign r_n = all_products[r_p].title | replace: ' ','_' %}
      {% for related_variant in all_products[r_p].variants %}
        {% if related_variant.id == r_v %} {% comment %} fails if r_v is a string {% endcomment %}
          {% assign r_i = related_variant.image.src }}
        {% endif %}
      {% endfor %}
      {% capture metafield_data %}{{metafield_data}}{{ r_p }},{{ r_v }},{{ r_i }},{{ r_n }}{% unless forloop.last %}|{% endunless %}{% endcapture %}
    {% endfor %}
    <option id="{{ variant.id }}" metafield-data={{ metafield_data }}{% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
{% endfor %}

“metafield_data”将包含所有相关的产品信息(产品、变体、变体图像)。

JS 替换“switchRelated(vId)”

function switchRelated(vId) {
    var list = $('ul.related-products');
    var vIdd = parseInt(vId);

    list.children().remove()

    var variant_matches = $('#vId').attr('metafield-data').split('|')

    for (var i=0; i < variant_matches.length; i++) {
        var items = variant_matches[i].split(',')
        list.append('<li><div class="image"><a href="/products/'+items[0]+'/?variant='+items[1]+'"><img src="'+items[2]+'" /></a></div><h4><a href="/products/'+items[0]+'?variant='item[2]'">'+items[3].replace('_','')+'</a></h4></li>'); 
    }
}    

通俗地说,您从元字段中获取产品句柄和变体 ID,并使用 Liquid(服务器端功能)向它们添加标题和图像。然后,您将它们与变体进行匹配,并在您再次使用的元素中分配一个数据变量来更改 html 元素。

附注代码很长并且没有正确对齐,我可能在这里和那里错过了代码标点符号。请检查它们。逻辑很简单,AJAX 的全部权重被移除并转移到正常的 HTML 调用。

【讨论】:

  • 谢谢@hymnZ 我只想明确指出,每个元字段都包含 3 种完全不同的产品及其变体 ID 的推荐。例如,如果我们有一张白色的桌子,我们希望相关的产品是一把白色的椅子、一盏白色的灯和一个白色的书柜。在您的示例中,您说“rph-1,rph-v-id-1|rph-1,rph-v-id-1|rph-1,rph-v-id-3”,但它更像是“rph -1,rph-v-id-1|rph-2,rph-v-id-1|rph-3,rph-v-id-1"。考虑到这一事实,您的代码是否仍能正常工作?
  • 我的错误。我在通勤时写了这个答案。它应该是 rph-1,rph-v-id-1|rph-2,rph-v-id-2|rph-3,rph-v-id-3 。我已经更新了答案。请随时指出其他错误。您可以拥有任意数量的不同/相同产品,并且代码将起作用。但请记住 Shopify 服务器限制。 1000 个可处理条目在一个完整的迭代中。所以有 10 个相关项目,每个项目有 100 个变体。
  • 元字段数据在 html 中返回空白 --> metafield-data=",0,,"
  • 将 split ',' 替换为 split: ',' 并将标题中的空格替换为 _ 并在 JavaScript 中反转它们。它现在在我这边工作。应该管用。检查修改后的代码。
  • 谢谢@HymnZ,但我们的产品只有 1 个选项,因此他们使用单选项选择器而不是产品选择。单选项选择器仅在 javascript 中使用 1 行而不是通过液体创建,我可以看到它正在创建的唯一行是--> return $('.single-option-selector#product-select-option-0' ).val(linkedVariantOption1).trigger('change');我不确定如何将您的代码与这行​​ javascript 一起使用来操作单个选项下拉列表
猜你喜欢
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
  • 2023-02-08
  • 2019-03-28
  • 1970-01-01
相关资源
最近更新 更多