造型在Shopify中售罄的选项

发布于 2025-02-02 02:22:41 字数 1208 浏览 1 评论 0原文

我正在尝试将CS​​S添加到产品选项中,以向用户提供视觉指示哪些选项不可用(已售罄)。当产品只有一组选项值时,这起作用,但是我的产品具有两个(“日期”和“时间”)。我在大多数方面都可以使用此操作,但是当我在日期之间切换时,可用的“时间”选项不会更新。这里的任何帮助将不胜感激。

在我的产品形式中,我有以下代码来添加一类以售罄的选项。也许我需要一些JS?

如果有帮助,我正在使用声望主题,并且页面在这里: https://neetfield.co。英国/比萨饼

                {%- if option.name == "Time" and product.selected_or_first_available_variant.option1 == product.variants[forloop.index0].option1 -%}
                  {%- if product.variants[forloop.index0].available -%}
                    {%- assign opt_sold = false -%}
                  {%- else -%}
                    {%- assign opt_sold = true -%}
                  {%- endif -%}
                {%- else -%}
                  {%- assign opt_sold = false -%}
                {%- endif -%}

然后,这用于添加一类以售罄选项{%如果Opt_sold%} Opt-Sold-Sold-out {%endif%}

这是我位置的屏幕截图到达(现在在实时网站上禁用,直到在日期之间切换时,我一直在工作):

“在此处输入图像说明”

I'm trying to add css to product options to provide the user with a visual indication of which options are not available (sold out). This works when a product only has one set of option values, however my product has two ("date", and "time"). I have this working most of the way, however the available "Time" options are not updated when I switch between dates. Any help here would be hugely appreciated.

Inside my product-form.liquid file I have the following code to add a class to sold out options. Perhaps I need some js?

In case it's helpful, I'm using the Prestige theme and the page is here: https://neetfield.co.uk/pizza

                {%- if option.name == "Time" and product.selected_or_first_available_variant.option1 == product.variants[forloop.index0].option1 -%}
                  {%- if product.variants[forloop.index0].available -%}
                    {%- assign opt_sold = false -%}
                  {%- else -%}
                    {%- assign opt_sold = true -%}
                  {%- endif -%}
                {%- else -%}
                  {%- assign opt_sold = false -%}
                {%- endif -%}

And then this is used to add a class to sold out options {% if opt_sold %}opt-sold-out{% endif %}

This is a screenshot of where I got to (now disabled on the live site until I haved it working when switching between dates):

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凹づ凸ル 2025-02-09 02:22:41

首页渲染(液体)

的初始页面加载您可以使用类似的内容:

{%- liquid
  assign selected_option_1 = product.selected_or_first_available_variant.option1
  assign relevant_variants = product.variants | where: 'option1', selected_option_1
  assign available_timeslots = ''

  for variant in relevant_variants
    if variant.available
      assign available_timeslots = available_timeslots | append: ',' | append: variant.option2
    endif
  endfor

  assign available_timeslots = available_timeslots | remove_first: ',' | split: ','
-%}

此片段在所有产品变体上迭代,其中option1等于option1 当前选择变体的值(例如,“ 6月4日,星期六”)。对于每个变体,我们将检查它是否可用,并将其推到opary_timeslots array。

确保在所有产品选项上迭代之前,将此片段放置。

最后,使用此数组检查选项值是否可用:

{%- unless available_timeslots contains value -%}
  Disable option input
{%- endunless -%}

value基本上是option.values的值。我敢肯定,您会在产品形式中找到它的某个位置:)

用户交互后(JavaScript),

由于Liquid是一种服务器端渲染模板语言,您只能通过更新通过JavaScript更新变体更改的选项输入元素来实现此目的在客户端。 Shopify Prestige主题具有有用的 customevent 对于这种风景: 变体:更改

实现的示例将如下所示:

/**
 * Gets the option index that is different between `variant` in `previousVariant`.
 *
 * @param {object} variant
 * @param {object} previousVariant
 * @returns {1 | 2 | 3}
 */
const getChangedOptionIndex = (variant, previousVariant) => {
  let changedOptionIndex;

  for (let i = 0; i < variant.options.length; i++) {
    if (variant.options[i] !== previousVariant.options[i]) {
      changedOptionIndex = i;
      break;
    }
  }

  return changedOptionIndex;
};

/**
 * Find a variant via its options.
 *
 * @param {object[]} variants
 * @param {{ option1: string, option2: string }} options
 * @returns {object | undefined}
 */
const findVariantByOptions = (variants, { option1, option2 }) => {
  return variants.find((variant) => variant.option1 === option1 && variant.option2 === option2);
};

const { product } = JSON.parse(document.querySelector('script[data-product-json]').innerHTML);

document.addEventListener('variant:changed', (event) => {
  // We might need a sanity check here. For example, if the current variant is
  // "Saturday 4th June / 18:30" and you switch to "Saturday 11th June" the time option
  // "18:30" might not exist which would result in `event.detail` being `undefined`.
  // if (!event.detail.variant) {
  //
  // }

  const { variant, previousVariant } = event.detail;
  const changedOptionIndex = getChangedOptionIndex(variant, previousVariant);

  const optionInputEls = document.querySelectorAll('input[name^="option-"]');

  // Note: This approach won't work anymore if a product has 3 options
  optionInputEls.forEach((optionInputEl) => {
    const optionIndex = Number(optionInputEl.name.split('-')[1]);

    // Only check option inputs that are not of the same group as the changed option
    if (optionIndex !== changedOptionIndex) {
      const foundVariant = findVariantByOptions(product.variants, {
        [`option${changedOptionIndex + 1}`]: variant.options[changedOptionIndex],
        [`option${optionIndex + 1}`]: optionInputEl.value,
      });

      if (!foundVariant || !foundVariant.available) {
        optionInputEl.nextElementSibling.classList.add('opt-sold-out');
      } else {
        optionInputEl.nextElementSibling.classList.remove('opt-sold-out');
      }
    }
  });
});

请记住,您并没有真正禁用输入。它只是在视觉上表明它是禁用的。如果这对您来说不是问题,请忽略此评论。

请注意,这无法处理以下方案:

  • 用户选择日期“ a”“
  • 用户选择时间” x“
  • 用户选择日期” b“(时间为“ x”),

我猜想选择日期的决定始终首先,这不应该是要担心的重要情况。

First page render (Liquid)

For the initial page load you can use something like this:

{%- liquid
  assign selected_option_1 = product.selected_or_first_available_variant.option1
  assign relevant_variants = product.variants | where: 'option1', selected_option_1
  assign available_timeslots = ''

  for variant in relevant_variants
    if variant.available
      assign available_timeslots = available_timeslots | append: ',' | append: variant.option2
    endif
  endfor

  assign available_timeslots = available_timeslots | remove_first: ',' | split: ','
-%}

This snippet iterates over all product variants where option1 equals the option1 value of the currently selected variant (e.g. "Saturday 4th June"). For each variant we'll check if its available and push it to the available_timeslots array.

Make sure to place this snippet before iterating over all product options.

Finally, use this array to check if an option value is available:

{%- unless available_timeslots contains value -%}
  Disable option input
{%- endunless -%}

value basically is a value of option.values. I'm sure you'll find this somewhere in your product-form :)

After user interaction (JavaScript)

Since Liquid is a server-side rendered template language, you can only achieve this by updating the option input elements on variant change via JavaScript on the client-side. The Shopify Prestige theme has a useful CustomEvent for this scenario: variant:changed

An example of the implementation would look like this:

/**
 * Gets the option index that is different between `variant` in `previousVariant`.
 *
 * @param {object} variant
 * @param {object} previousVariant
 * @returns {1 | 2 | 3}
 */
const getChangedOptionIndex = (variant, previousVariant) => {
  let changedOptionIndex;

  for (let i = 0; i < variant.options.length; i++) {
    if (variant.options[i] !== previousVariant.options[i]) {
      changedOptionIndex = i;
      break;
    }
  }

  return changedOptionIndex;
};

/**
 * Find a variant via its options.
 *
 * @param {object[]} variants
 * @param {{ option1: string, option2: string }} options
 * @returns {object | undefined}
 */
const findVariantByOptions = (variants, { option1, option2 }) => {
  return variants.find((variant) => variant.option1 === option1 && variant.option2 === option2);
};

const { product } = JSON.parse(document.querySelector('script[data-product-json]').innerHTML);

document.addEventListener('variant:changed', (event) => {
  // We might need a sanity check here. For example, if the current variant is
  // "Saturday 4th June / 18:30" and you switch to "Saturday 11th June" the time option
  // "18:30" might not exist which would result in `event.detail` being `undefined`.
  // if (!event.detail.variant) {
  //
  // }

  const { variant, previousVariant } = event.detail;
  const changedOptionIndex = getChangedOptionIndex(variant, previousVariant);

  const optionInputEls = document.querySelectorAll('input[name^="option-"]');

  // Note: This approach won't work anymore if a product has 3 options
  optionInputEls.forEach((optionInputEl) => {
    const optionIndex = Number(optionInputEl.name.split('-')[1]);

    // Only check option inputs that are not of the same group as the changed option
    if (optionIndex !== changedOptionIndex) {
      const foundVariant = findVariantByOptions(product.variants, {
        [`option${changedOptionIndex + 1}`]: variant.options[changedOptionIndex],
        [`option${optionIndex + 1}`]: optionInputEl.value,
      });

      if (!foundVariant || !foundVariant.available) {
        optionInputEl.nextElementSibling.classList.add('opt-sold-out');
      } else {
        optionInputEl.nextElementSibling.classList.remove('opt-sold-out');
      }
    }
  });
});

Keep in mind that you are not really disabling the input. It's just visually indicating that it's disabled. If that's not a problem for you, just ignore this comment.

Note that this does not handle the following scenario:

  • User chooses date "A"
  • User chooses time "X"
  • User chooses date "B" (where time "X" is not available)

I'm guessing that the decision which date to chose always comes first so this should not be an important scenario to worry about.

柳若烟 2025-02-09 02:22:41

具有单一选项的产品的方法

非常容易,并且不需要任何JavaScript,因为每个选项值映射恰好是一个变体。去这里的方法是获取该变体并检查是否可用:

{%- for option in product.options_with_values -%}
  {%- for value in option.values -%}
    {%- assign variant = product.variants | where: 'option1', value -%}

    {%- if variant.available == false -%}
      Disable option input
    {%- endif -%}
  {%- endfor -%}
{%- endfor -%}

Approach for products with a single option

This case is pretty easy and does not require any JavaScript since each option value maps to exactly one variant. The way to go here would be to get that variant and check if it's available:

{%- for option in product.options_with_values -%}
  {%- for value in option.values -%}
    {%- assign variant = product.variants | where: 'option1', value -%}

    {%- if variant.available == false -%}
      Disable option input
    {%- endif -%}
  {%- endfor -%}
{%- endfor -%}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文