首页 > 解决方案 > Shopify 产品列表中的变体

问题描述

在shopify上,我创建了一个具有可见颜色变体的产品列表,而无需输入产品,但在页面中前进,产品始终相同且永不改变,而且产品计数是错误的,因为它将产品计数为仍然没有外部颜色变体。

谁能帮我解决这个问题?

这是我的产品页面,我在其中使用您的指南:

{%- comment -%}Color labels used to detect what is a color swatch{%- endcomment -%}
{%- assign color_label = 'color,colour,couleur,cor,colore,farbe,색,色,カラー,färg,farve,szín' | split: ',' -%}
{%- for product in collection.products -%}

{% assign options = product.options %}
{% assign have_color = false %}

{% for option in options %}
{% comment %}Check if there is a color option{% endcomment %}
{% if option == "Color" or option == "Colore" %}
{% assign have_color = forloop.index0 %}
{% endif %}
{% endfor %}


{% if have_color != false %}
{% assign variants = product.variants %}
{% assign colorlist = '' %}
{% assign color = '' %}

{% for variant in variants %}
{% capture color %}
{{ variant.options[have_color] }}
{% endcapture %}


{% unless colorlist contains color %}

{% assign product = variant %}
<div class="product-item {% if horizontal %}product-item--horizontal{% elsif list %}product-item--list{% else %}product-item--vertical{% endif %} {% if section.id == 'blog-sidebar' %}product-item--compact{% endif %} {{ grid_classes }}">
  {%- capture product_labels -%}
  {%- unless hide_labels -%}
  {%- for tag in product.tags -%}
  {%- if tag contains '__label:' -%}
  <span class="product-label product-label--custom1">{{ tag | split: '__label:' | last }}</span>
  {%- endif -%}

  {%- if tag contains '__label1:' -%}
  <span class="product-label product-label--custom1">{{ tag | split: '__label1:' | last }}</span>
  {%- endif -%}

  {%- if tag contains '__label2:' -%}
  <span class="product-label product-label--custom2">{{ tag | split: '__label2:' | last }}</span>
  {%- endif -%}
  {%- endfor -%}

  {%- if settings.show_discount and product.price < product.compare_at_price -%}
  {%- if settings.discount_mode == 'percentage' -%}
  {%- assign savings = product.compare_at_price | minus: product.price | times: 100.0 | divided_by: product.compare_at_price | round | append: '%' -%}
  {%- else -%}
  {%- capture savings -%}<span>{{ product.compare_at_price | minus: product.price | money }}</span>{%- endcapture -%}
  {%- endif -%}

  <span class="product-label product-label--on-sale">{{ 'collection.product.discount_html' | t: savings: savings }}</span>
  {%- endif -%}
  {%- endunless -%}
  {%- endcapture -%}

  {%- if product_labels != blank -%}
  <div class="product-item__label-list">
    {{- product_labels -}}
  </div>
  {%- endif -%}

  {%- if settings.show_secondary_image and product.media.size > 1 -%}
  {%- assign show_secondary_media = true -%}
  {%- else -%}
  {%- assign show_secondary_media = false -%}
  {%- endif -%}

  {%- assign filtered_variant = '' -%}

  {%- if product.media == blank -%}
  <a href="{{ filtered_variant.url | default: product.url | within: collection }}" class="product-item__image-wrapper {% if show_secondary_media %}product-item__image-wrapper--with-secondary{% endif %}">
    {%- capture placeholder -%}{% cycle 'product-2', 'product-1', 'product-3', 'product-4', 'product-5', 'product-6' %}{% endcapture %}
    {{- placeholder | placeholder_svg_tag: 'placeholder-svg' -}}
  </a>
  {%- endif -%}

  {%- if product.media.size > 0 -%}
  {%- comment -%}
  Are you ready for some Liquid crazyness? Let's start!
  The idea here is that when we are on a collection page that is filtered using a color swatch, instead of showing the featured
  image, we'd like to show a variant image that is attached to the selected color. Unfortunately, because filtering is done using
  tag, there is no direct relationship between tags and variants. We therefore have to do some crazy processing to match a filter
  with a variant. Because this code is within a collection page, it is executed for each product, so it's pretty performance
  sensitive. Disabling this piece of code may slightly improve the performance if you have lot of variants.
  {%- endcomment -%}

  {%- assign primary_media = variant.featured_media -%}

  {%- if request.page_type == 'collection' and section.settings.show_filters and section.settings.filter_type == 'group' -%}
  {%- assign matched_color_option = '' -%}

  {%- for tag in current_tags -%}
  {%- assign tag_parts = tag | split: '_' -%}
  {%- assign tag_group_name = tag_parts | first | downcase -%}
  {%- assign tag_group_value = tag_parts | last | downcase -%}

  {%- if color_label contains tag_group_name -%}
  {%- comment -%}We have found a matching color label, then we check if this product contains an option named the same{%- endcomment -%}

  {%- for option in product.options -%}
  {%- assign downcased_option = option | downcase -%}

  {%- if downcased_option == tag_group_name -%}
  {%- comment -%}We have found the index of the matching option, so we can iterate through the variants{%- endcomment -%}
  {%- assign option_index = 'option' | append: forloop.index -%}

  {%- for variant in product.variants -%}

  {%- assign variant_option_value = variant[option_index] | downcase -%}

  {%- if variant_option_value == tag_group_value and variant.featured_media -%}
  {%- assign primary_media = variant.featured_media -%}
  {%- assign filtered_variant = variant -%}
  {%- break -%}
  {%- endif %}
              {%- endfor -%}

  {%- break -%}
  {%- endif -%}
  {%- endfor -%}

  {%- break -%}
  {%- endif -%}
  {%- endfor -%}
  {%- endif -%}

  <a href="{{ filtered_variant.url | default: product.url | within: collection }}" class="product-item__image-wrapper {% if show_secondary_media %}product-item__image-wrapper--with-secondary{% endif %}">
    {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: primary_media.preview_image -%}{%- endcapture -%}
    {%- assign image_url = primary_media | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
    <div class="aspect-ratio {% if settings.product_image_size != 'natural' %}aspect-ratio--{{ settings.product_image_size }}{% endif %}" style="padding-bottom: {{ 100.0 | divided_by: primary_media.preview_image.aspect_ratio }}%; z-index: -1;">
      <img class="product-item__primary-image lazyload image--fade-in" data-media-id="{{ primary_media.id }}" data-src="{{ image_url }}" data-sizes="auto" data-widths="[{{ supported_sizes }}]" alt="{{ primary_media.alt | escape }}">

      {%- if show_secondary_media -%}
      {%- if forloop.index0 == 0-%}

      {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: product.media[1].preview_image -%}{%- endcapture -%}
      {%- assign image_url = product.media[1] | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
      {%- endif -%}                                     
      {%- if forloop.index0 == 1 -%}
      {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: product.media[9].preview_image -%}{%- endcapture -%}
      {%- assign image_url = product.media[9] | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}

      {%- endif -%}
      {%- if forloop.index0 == 2 -%}
      {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: product.media[17].preview_image -%}{%- endcapture -%}
      {%- assign image_url = product.media[17] | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}

      {%- endif -%}
      {%- if forloop.index0 == 3 -%}
      {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: product.media[25].preview_image -%}{%- endcapture -%}
      {%- assign image_url = product.media[25] | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}

      {%- endif -%}
      {%- if forloop.index0 == 4 -%}
      {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: product.media[33].preview_image -%}{%- endcapture -%}
      {%- assign image_url = product.media[33] | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}

      {%- endif -%}

      <img class="product-item__secondary-image lazyload image--fade-in" data-src="{{ image_url }}" data-sizes="auto" data-widths="[{{ supported_sizes }}]" alt="{{ product.media[1].alt | escape }}">

      {%- endif -%}

      <noscript>
        <img src="{{ primary_image | img_url: '600x' }}" alt="{{ primary_media.alt | escape }}">
      </noscript>
    </div>
  </a>
  {%- endif -%}

  <div class="product-item__info">
    <div class="product-item__info-inner arrow white">
      {%- capture price_list -%}
      <div class="product-item__price-list price-list">
        {%- if product.price < product.compare_at_price -%}
        {%- if product.price_varies -%}
        {%- capture price_min -%}<span>{{ product.price_min | money }}</span>{%- endcapture -%}
        {%- capture price_max -%}<span>{{ product.price_max | money }}</span>{%- endcapture -%}
        <span class="price price--highlight ">
          <span class="visually-hidden">{{ 'product.general.sale_price' | t }}</span>
          {{price_min}}
        </span>

        <span class="price price--compare text-compare">
          <span class="visually-hidden">{{ 'product.general.regular_price' | t }}</span>
          {{- product.compare_at_price_min | money -}}
        </span>
        {%- else -%}
        <span class="price price--highlight">
          <span class="visually-hidden">{{ 'product.general.sale_price' | t }}</span>
          {{- product.price | money -}}
        </span>

        <span class="price price--compare">
          <span class="visually-hidden">{{ 'product.general.regular_price' | t }}</span>
          {{- product.compare_at_price | money -}}
        </span>
        {%- endif -%}
        {%- elsif product.price_varies -%}
        {%- capture price_min -%}<span>{{ product.price_min | money }}</span>{%- endcapture -%}
        {%- capture price_max -%}<span>{{ product.price_max | money }}</span>{%- endcapture -%}

        <span class="price">
          <span class="visually-hidden">{{ 'product.general.sale_price' | t }}</span>
          {{- 'collection.product.from_price_html' | t: price_min: price_min, price_max: price_max -}}
        </span>
        {%- else -%}
        <span class="price">
          <span class="visually-hidden">{{ 'product.general.sale_price' | t }}</span>
          {{- product.price | money -}}
        </span>
        {%- endif -%}
      </div>
      <span class="shopify-product-reviews-badge" data-id="{{ product.id }}"></span>

      {%- if product.selected_or_first_available_variant.unit_price_measurement -%}
      <div class="product-item__price-info">
        <div class="unit-price-measurement">
          <span class="unit-price-measurement__price">{{ product.selected_or_first_available_variant.unit_price | money }}</span>
          <span class="unit-price-measurement__separator">/ </span>

          {%- if product.selected_or_first_available_variant.unit_price_measurement.reference_value != 1 -%}
          <span class="unit-price-measurement__reference-value">{{ product.selected_or_first_available_variant.unit_price_measurement.reference_value }}</span>
          {%- endif -%}

          <span class="unit-price-measurement__reference-unit">{{ product.selected_or_first_available_variant.unit_price_measurement.reference_unit }}</span>
        </div>
      </div>
      {%- endif -%}
      {%- endcapture -%}

      {%- capture vendor -%}
      {%- if settings.show_vendor -%}
      {%- assign vendor_handle = product.vendor | handle -%}
      {%- assign collection_for_vendor = collections[vendor_handle] -%}

      {%- unless collection_for_vendor.empty? -%}
      <a class="product-item__vendor link" href="{{ collection_for_vendor.url }}">{{ product.vendor }}</a>
      {%- else -%}
      <a class="product-item__vendor link" href="{{ product.vendor | url_for_vendor }}">{{ product.vendor }}</a>
      {%- endunless -%}
      {%- endif -%}
      {%- endcapture -%}

      {%- if settings.product_price_position == 'before_title' -%}
      {{ price_list }}
      {%- endif -%}

      {%- if settings.product_price_position == 'after_title' -%}
      {{ vendor }}
      {%- endif -%}

      <a href="{{ filtered_variant.url | default: product.url | within: collection }}" class="product-item__title text--strong link">{{ product.title }}</a>

      {%- if settings.product_price_position == 'before_title' -%}
      {{ vendor }}
      {%- endif -%}

      {%- if settings.show_color_swatch and template != 'blog' -%}
      {%- capture color_swatch -%}
      {%- capture color_name -%}{{ section.id }}-{{ product.id }}{%- endcapture -%}

      {%- for option in product.options_with_values -%}
      {%- assign downcased_option = option.name | downcase -%}

      {%- if color_label contains downcased_option -%}
      {%- assign variant_option = 'option' | append: forloop.index -%}
      {%- assign value_to_match = filtered_variant[variant_option] | default: option.selected_value -%}

      {%- for value in option.values -%}
      {%- assign downcased_value = value | downcase -%}
      {%- capture color_id -%}{{ color_name }}-{{ forloop.index }}{%- endcapture -%}

      {%- for variant in product.variants -%}
      {%- if variant[variant_option] == value -%}
      {%- assign variant_for_value = variant -%}
      {%- break -%}
      {%- endif -%}
      {%- endfor -%}

      <div class="color-swatch {% if downcased_value == 'white' or downcased_value == 'blanc' %}color-swatch--white{% endif %}">
        {%- if variant_for_value.featured_media -%}
        {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,500,600,700,800', image: variant_for_value.featured_media.preview_image -%}{%- endcapture -%}
        {%- assign image_url = variant_for_value.featured_media | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
        {%- endif -%}

        {%- assign color_swatch_name = value | handle | append: '.png' -%}
        {%- assign color_swatch_image = images[color_swatch_name] -%}

        <input class="color-swatch__radio" type="radio" name="{{ color_name }}" id="{{ color_id }}" value="{{ value | escape }}" {% if value_to_match == value %}checked="checked"{% endif %} data-variant-url="{{ variant_for_value.url }}" {% if variant_for_value.featured_media %}data-media-id="{{ variant_for_value.featured_media.id }}" data-image-url="{{ image_url }}" data-image-widths="[{{ supported_sizes }}]" data-image-aspect-ratio="{{ variant_for_value.featured_media.preview_image.aspect_ratio }}"{% endif %} aria-label="{{ value | escape }}">
        <label class="color-swatch__item lazyload" for="{{ color_id }}" {% if color_swatch_image != blank %}data-bg="{{ color_swatch_image | img_url: '64x64' }}"{% else %}style="background-color: {{ value | replace: ' ', '' | downcase }}"{% endif %} title="{{ value | escape }}">
          <span class="visually-hidden">{{ value }}</span>
        </label>
        <a href="{{ product.url }}" class="color-swatch__item-link">+{{ option.values.size | minus: forloop.index0 }}</a>
      </div>
      {%- endfor -%}
      {%- endif -%}
      {%- endfor -%}
      {%- endcapture -%}

      {%- if color_swatch != blank -%}
      <div class="product-item__swatch-list">
        <div class="color-swatch-list">
          {{ color_swatch }}
        </div>
      </div>
      {%- endif -%}
      {%- endif -%}

      {%- if settings.product_price_position == 'after_title' -%}
      {{ price_list }}
      {%- endif -%}

      {%- if settings.show_reviews_badge -%}
      <a class="product-item__reviews-badge link" href="{{ product.url | within: collection }}#product-reviews">
        <span class="visually-hidden">{{ 'product.general.reviews' | t }}</span>

        <span class="shopify-product-reviews-badge" data-id="{{ product.id }}">
          {%- comment -%}Display a placeholder, to allocate space{%- endcomment -%}
          <div class="spr-badge" style="opacity: 0">
            <span class="spr-starrating spr-badge-starrating">
              <i class="spr-icon spr-icon-star-empty"></i>
              <i class="spr-icon spr-icon-star-empty"></i>
              <i class="spr-icon spr-icon-star-empty"></i>
              <i class="spr-icon spr-icon-star-empty"></i>
              <i class="spr-icon spr-icon-star-empty"></i>
            </span>
          </div>
        </span>
      </a>
      {%- endif -%}

      {%- if settings.show_inventory_quantity and product.template_suffix != 'pre-order' -%}
      {%- if product.available -%}
      {%- assign should_calculate_inventory = true -%}

      {%- for variant in product.variants -%}
      {%- comment -%}
      If we have one variant that is set to "continue" or that do not have any inventory management, then we skip the calculation of inventory as this
      means at least one of the variant is always purchasable
      {%- endcomment -%}

      {%- if variant.inventory_policy == 'continue' or variant.inventory_management == null -%}
      {%- assign should_calculate_inventory = false -%}
      {%- break -%}
      {%- endif -%}
      {%- endfor -%}

      {%- if should_calculate_inventory and settings.low_inventory_threshold > 0 -%}
      {%- assign all_inventory = 0 -%}

      {%- for variant in product.variants -%}
      {%- if variant.inventory_management -%}
      {%- assign all_inventory = variant.inventory_quantity | at_least: 0 | plus: all_inventory -%}
      {%- endif -%}
      {%- endfor -%}

      {%- if all_inventory <= settings.low_inventory_threshold -%}
      <span class="product-item__inventory inventory inventory--low">{{ 'collection.product.low_stock_with_quantity_count' | t: count: all_inventory }}</span>
      {%- else -%}
      <span class="product-item__inventory inventory inventory--high">{{ 'collection.product.in_stock_with_quantity_count' | t: count: all_inventory }}</span>
      {%- endif -%}
      {%- else -%}
      {%- if product.variants.first.inventory_policy == 'continue' and product.variants.first.inventory_quantity <= 0 and product.variants.first.requires_shipping -%}
      <span class="product-item__inventory inventory inventory--high">{{ 'collection.product.oversell_stock' | t }}</span>
      {%- else -%}
      <span class="product-item__inventory inventory inventory--high">{{ 'collection.product.in_stock' | t }}</span>
      {%- endif -%}
      {%- endif -%}
      {%- else -%}
      <span class="product-item__inventory inventory">{{ 'collection.product.sold_out' | t }}</span>
      {%- endif -%}
      {%- endif -%}
    </div>

    {%- if request.page_type == 'collection' or request.page_type == 'search' or show_add_to_cart -%}
    {%- if section.settings.show_quick_view == 'list_grid' or section.settings.show_quick_buy == 'list_grid' or show_add_to_cart -%}
    {%- assign product_form_classes = 'product-item__action-list button-stack' -%}
    {%- else -%}
    {%- assign product_form_classes = 'product-item__action-list product-item__action-list--list-view-only button-stack' -%}
    {%- endif -%}

    {%- assign form_id = 'product_form_id_' | append: product.id | append: '_' | append: section.id -%}

    {%- if product.template_suffix == 'contact' -%}
    <div class="{{ product_form_classes }}">
      <a href="mailto:{{ shop.email }}" class="product-item__action-button button button--small button--primary">
        {{- 'product.form.contact_us' | t -}}
      </a>
    </div>
    {%- else -%}
    {%- form 'product', product, id: form_id, class: product_form_classes -%}
    <input type="hidden" name="quantity" value="1">
    <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">

    {%- if section.settings.show_quick_buy == 'list_grid' or show_add_to_cart -%}
    {%- assign quick_buy_classes = 'product-item__action-button button button--small button--primary' -%}
    {%- else -%}
    {%- assign quick_buy_classes = 'product-item__action-button product-item__action-button--list-view-only button button--small button--primary' -%}
    {%- endif -%}

    {%- if product.available -%}
    {%- if product.variants.size == 1 -%}
    <button type="submit" class="{{ quick_buy_classes }}" data-action="add-to-cart">
      {%- if product.template_suffix == 'pre-order' -%}
      {{- 'collection.product.pre_order' | t -}}
      {%- else -%}
      {{- 'collection.product.add_to_cart' | t -}}
      {%- endif -%}
    </button>
    {%- else -%}
    <a href="{{ product.url | within: collection }}" class="{{ quick_buy_classes }}">{{ 'collection.product.choose_options' | t }}</a>
    {%- endif -%}
    {%- else -%}
    <button class="{{ quick_buy_classes | replace: 'button--primary', 'button--disabled' }}" disabled>{{ 'collection.product.sold_out' | t }}</button>
    {%- endif -%}

    {%- if section.settings.show_quick_view == 'list_grid' -%}
    {%- assign quick_view_classes = 'product-item__action-button button button--small button--ternary hidden-phone' -%}
    {%- else -%}
    {%- assign quick_view_classes = 'product-item__action-button product-item__action-button--list-view-only button button--small button--ternary hidden-phone' -%}
    {%- endif -%}

    <button type="button" class="{{ quick_view_classes }}" data-action="open-modal" data-secondary-action="open-quick-view" aria-controls="modal-quick-view-{{ section.id }}" data-product-url="{{ product.url }}">{{ 'collection.product.quick_view' | t }}</button>
    {%- endform -%}
    {%- endif -%}
    {%- endif -%}
  </div>
</div>

{% capture tempList %}
{{colorlist | append: color | append: ' '}}
{% endcapture %}

{% assign colorlist = tempList %}
{% endunless %}
{% endfor %}
{% endif %}
{%- endfor -%}

这是我的分页页面:

{%- if paginate.pages > 1 -%}
  <div class="pagination">
    <div class="pagination__inner">
      {%- if paginate.previous -%}
        <a class="pagination__prev link" rel="prev" title="{{ 'general.pagination.previous_page' | t }}" data-page="{{ paginate.current_page | minus: 1 }}" href="{{ paginate.previous.url }}{{ hash }}">
          {%- render 'icon', icon: 'arrow-left' -%} {{- 'general.pagination.previous_page' | t -}}
        </a>
      {%- endif -%}

      <div class="pagination__nav">
        {%- for part in paginate.parts -%}
          {%- if part.is_link -%}
            <a href="{{ part.url }}{{ hash }}" data-page="{{ part.title }}" class="pagination__nav-item link" title="{{ 'general.pagination.go_to_page' | t: page: part.title }}">{{ part.title }}</a>
          {%- else -%}
            <span class="pagination__nav-item {% if part.title == paginate.current_page %}is-active{% endif %}">{{ part.title }}</span>
          {%- endif -%}
        {%- endfor -%}
      </div>

      <span class="pagination__page-count">{{ 'general.pagination.page_count' | t: current_page: paginate.current_page, pages: paginate.pages }}</span>

      {%- if paginate.next -%}
        <a class="pagination__next link" rel="next" title="{{ 'general.pagination.next_page' | t }}" data-page="{{ paginate.current_page | plus: 1 }}" href="{{ paginate.next.url }}{{ hash }}">
          {{- 'general.pagination.next_page' | t -}} {%- render 'icon', icon: 'arrow-right' -%}
        </a>
      {%- endif -%}
    </div>
  </div>
{%- endif -%}

谢谢

标签: shopifyliquid

解决方案


推荐阅读