在 Shopify 中设计售罄选项
Styling Sold Out Options in Shopify
我正在尝试将 css 添加到产品选项中,以便为用户提供哪些选项不可用(已售罄)的视觉指示。当产品只有一组选项值时,此方法有效,但我的产品有两个(“日期”和“时间”)。我大部分时间都在使用此功能,但是当我在日期之间切换时,可用的“时间”选项不会更新。非常感谢此处的任何帮助。
在我的 product-form.liquid 文件中,我有以下代码来添加 class 到已售罄的选项。也许我需要一些 js?
如果有帮助,我使用的是 Prestige 主题,页面位于此处: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 -%}
然后这用于添加 class 到售罄选项 {% if opt_sold %}opt-sold-out{% endif %}
这是我到达的地方的屏幕截图(现在在实时网站上被禁用,直到我在日期之间切换时让它工作):
第一页呈现(液体)
对于初始页面加载,您可以使用如下内容:
{%- 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 日,星期六”)。对于每个变体,我们将检查其是否可用并将其推送到 available_timeslots
数组。
确保在遍历所有产品选项之前放置此代码段。
最后,使用此数组检查选项值是否可用:
{%- unless available_timeslots contains value -%}
Disable option input
{%- endunless -%}
value
基本上就是一个option.values
的值。我相信您会在 product-form 的某处找到它 :)
用户互动后(JavaScript)
由于 Liquid 是一种 server-side 呈现的模板语言,您只能通过 client-side 上的 JavaScript 更新变体更改时的选项输入元素来实现此目的。 Shopify Prestige 主题对这种情况很有用 CustomEvent:variant:changed
实施示例如下所示:
/**
* 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”不可用)
我猜选择日期的决定总是最先发生的,所以这应该不是一个需要担心的重要场景。
我正在尝试将 css 添加到产品选项中,以便为用户提供哪些选项不可用(已售罄)的视觉指示。当产品只有一组选项值时,此方法有效,但我的产品有两个(“日期”和“时间”)。我大部分时间都在使用此功能,但是当我在日期之间切换时,可用的“时间”选项不会更新。非常感谢此处的任何帮助。
在我的 product-form.liquid 文件中,我有以下代码来添加 class 到已售罄的选项。也许我需要一些 js?
如果有帮助,我使用的是 Prestige 主题,页面位于此处: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 -%}
然后这用于添加 class 到售罄选项 {% if opt_sold %}opt-sold-out{% endif %}
这是我到达的地方的屏幕截图(现在在实时网站上被禁用,直到我在日期之间切换时让它工作):
第一页呈现(液体)
对于初始页面加载,您可以使用如下内容:
{%- 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 日,星期六”)。对于每个变体,我们将检查其是否可用并将其推送到 available_timeslots
数组。
确保在遍历所有产品选项之前放置此代码段。
最后,使用此数组检查选项值是否可用:
{%- unless available_timeslots contains value -%}
Disable option input
{%- endunless -%}
value
基本上就是一个option.values
的值。我相信您会在 product-form 的某处找到它 :)
用户互动后(JavaScript)
由于 Liquid 是一种 server-side 呈现的模板语言,您只能通过 client-side 上的 JavaScript 更新变体更改时的选项输入元素来实现此目的。 Shopify Prestige 主题对这种情况很有用 CustomEvent:variant:changed
实施示例如下所示:
/**
* 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”不可用)
我猜选择日期的决定总是最先发生的,所以这应该不是一个需要担心的重要场景。