Shopify Debut 主题中的多文件上传器
Multi file uploader in Shopify Debut theme
我正在自定义我的页面以上传多个文件(照片)。这是我到目前为止的代码,根据这个 link 它应该可以工作:
https://shopify.dev/tutorials/customize-theme-get-customization-information-for-products
在 link 中转到 "Allow file uploads" 如果你想检查。
{% form 'product', product, class:form_classes, data-product-form: '', enctype:"multipart/form-data" %}
{% unless product.has_only_default_variant %}
<div class="product-form__controls-group">
{% for option in product.options_with_values %}
<div class="selector-wrapper js product-form__item">
<select class="single-option-selector single-option-selector-{{ section.id }} product-form__input"
id="SingleOptionSelector-{{ forloop.index0 }}"
data-index="option{{ forloop.index }}"
>
{% for value in option.values %}
<option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
{% endunless %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{%- if variant == current_variant %} selected="selected" {%- endif -%}
>
{{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
</option>
{% endfor %}
</select>
{% if section.settings.show_quantity_selector %}
{% comment %}
<div class="product-form__controls-group">
<div class="product-form__item">
<input type="number" id="Quantity-{{ section.id }}"
name="quantity" value="1" min="1" pattern="[0-9]*"
class="product-form__input product-form__input--quantity" data-quantity-input
>
</div>
</div>
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
{% endcomment %}
{% endif %}
<div class="product-form__error-message-wrapper product-form__error-message-wrapper--hidden{% if section.settings.enable_payment_button %} product-form__error-message-wrapper--has-payment-button{% endif %}"
data-error-message-wrapper
role="alert"
>
<span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span>
{% include 'icon-error' %}
<span class="product-form__error-message" data-error-message>{{ 'products.product.quantity_minimum_message' | t }}</span>
</div>
<div class="product-form__controls-group product-form__controls-group--submit">
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
<div class="product-form__item product-form__item--submit
{%- if section.settings.enable_payment_button %} product-form__item--payment-button {%- endif -%}
{%- if product.has_only_default_variant %} product-form__item--no-variants {%- endif -%}"
>
<button type="submit" name="add"
{% unless current_variant.available %} aria-disabled="true"{% endunless %}
aria-label="{% unless current_variant.available %}{{ 'products.product.sold_out' | t }}{% else %}{{ 'products.product.add_to_cart' | t }}{% endunless %}"
class="btn product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}"
data-add-to-cart>
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
<span class="hide" data-loader>
{% include 'icon-spinner' %}
</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
</div>
</div>
{% endform %}
这是我的表格,根据 link 必须具有属性
enctype = "multipart / form-data".
表单底部的输入类型 = "file"。
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
这是购物车中的代码-template.liquid。
<div class="list-view-item__title">
<a href="{{ item.url }}" class="cart__product-title" data-cart-item-title>
{{ item.product.title }}<br>
{% assign property_size = item.properties | size %}
{% if property_size > 0 %}
{% for p in item.properties %}
{{ item.properties.count }}
{% assign first_character_in_key = p.first | truncate: 1, '' %}
{% unless p.last == blank or first_character_in_key == '_' %}
{{ p.first }}:
{% if p.last contains '/uploads/' %}
<a class="lightbox" href="{{ p.last }}">{{ property_size }}</a>
{% else %}
{{ p.last }}
{% endif %}
<br>
{% endunless %}
{% endfor %}
{% endif %}
</a>
</div>
问题是即使我上传了两张或更多图片,property_size 变量的值为 1,而实际上我应该 return 项目具有的属性数量。
谁能帮帮我吗?我做错了什么?
本教程上传后,Debut 主题可能已更改,并且由于不受支持,可能不会更新。
如果您添加 type="text"
输入而不是 type="file"
,则会按预期添加 属性。发生这种情况是因为 _initAddToCart
函数(assets/theme.js
行 6447)获取表单 HTML 元素并将其传递给另一个函数。
var $data = $(this.selectors.productForm, this.$container);
this._addItemToCart($data);
然后在_addItemToCart
函数中(assets/theme.js
行6513),形式是serialized转成一个字符串:
var params = {
url: '/cart/add.js',
data: $(data).serialize(),
dataType: 'json',
};
$.post(params).done(...
此函数将忽略文件输入,如 jQuery 文档中所述:
Data from file select elements is not serialized.
要发送文件,必须设置FormData browser API can be used. But to use it with the jQuery AJAX call, some properties:
var params = {
url: '/cart/add.js',
// data: $(data).serialize(),
dataType: 'json',
// Disable the jQuery data processing, and send the FormData object
contentType: false,
processData: false,
data: new FormData($(data).get()[0])
};
$.post(params).done(...
但是,由于 HTML 文件 <input>
有 name="properties[Photo]"
,只有最后一个上传的文件会被添加到购物车项目的 Photo
属性.
我尝试使用 name="properties[Photo][]"
,但 cart/add.js
仅调用 returns 错误 500 并显示消息 "Internal Server Error".
因此,要上传多个文件,您可以将一些自定义代码添加到 _addItemToCart
函数中,让每个 File from the <input>
and add to the FormData 每个文件都有不同的密钥。
我正在自定义我的页面以上传多个文件(照片)。这是我到目前为止的代码,根据这个 link 它应该可以工作: https://shopify.dev/tutorials/customize-theme-get-customization-information-for-products 在 link 中转到 "Allow file uploads" 如果你想检查。
{% form 'product', product, class:form_classes, data-product-form: '', enctype:"multipart/form-data" %}
{% unless product.has_only_default_variant %}
<div class="product-form__controls-group">
{% for option in product.options_with_values %}
<div class="selector-wrapper js product-form__item">
<select class="single-option-selector single-option-selector-{{ section.id }} product-form__input"
id="SingleOptionSelector-{{ forloop.index0 }}"
data-index="option{{ forloop.index }}"
>
{% for value in option.values %}
<option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
{% endunless %}
<select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{%- if variant == current_variant %} selected="selected" {%- endif -%}
>
{{ variant.title }} {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
</option>
{% endfor %}
</select>
{% if section.settings.show_quantity_selector %}
{% comment %}
<div class="product-form__controls-group">
<div class="product-form__item">
<input type="number" id="Quantity-{{ section.id }}"
name="quantity" value="1" min="1" pattern="[0-9]*"
class="product-form__input product-form__input--quantity" data-quantity-input
>
</div>
</div>
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
{% endcomment %}
{% endif %}
<div class="product-form__error-message-wrapper product-form__error-message-wrapper--hidden{% if section.settings.enable_payment_button %} product-form__error-message-wrapper--has-payment-button{% endif %}"
data-error-message-wrapper
role="alert"
>
<span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span>
{% include 'icon-error' %}
<span class="product-form__error-message" data-error-message>{{ 'products.product.quantity_minimum_message' | t }}</span>
</div>
<div class="product-form__controls-group product-form__controls-group--submit">
<div class="qtydiv">
{% comment %}<label for="Quantity" class="quantity-selector">Quantity</label>{% endcomment %}
<div class="qtybox">
<span class="btnqty qtyminus icon icon-minus">-</span>
<input type="text" id="quantity" name="quantity" value="1" min="1" class="quantity-selector quantity-input" readonly="">
<span class="btnqty qtyplus icon icon-plus">+</span>
</div>
</div>
<div class="product-form__item product-form__item--submit
{%- if section.settings.enable_payment_button %} product-form__item--payment-button {%- endif -%}
{%- if product.has_only_default_variant %} product-form__item--no-variants {%- endif -%}"
>
<button type="submit" name="add"
{% unless current_variant.available %} aria-disabled="true"{% endunless %}
aria-label="{% unless current_variant.available %}{{ 'products.product.sold_out' | t }}{% else %}{{ 'products.product.add_to_cart' | t }}{% endunless %}"
class="btn product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}"
data-add-to-cart>
<span data-add-to-cart-text>
{% unless current_variant.available %}
{{ 'products.product.sold_out' | t }}
{% else %}
{{ 'products.product.add_to_cart' | t }}
{% endunless %}
</span>
<span class="hide" data-loader>
{% include 'icon-spinner' %}
</span>
</button>
{% if section.settings.enable_payment_button %}
{{ form | payment_button }}
{% endif %}
</div>
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
</div>
</div>
{% endform %}
这是我的表格,根据 link 必须具有属性
enctype = "multipart / form-data".
表单底部的输入类型 = "file"。
<input required class="required product-form__input" id="photo" type="file" name="properties[Photo]" multiple>
这是购物车中的代码-template.liquid。
<div class="list-view-item__title">
<a href="{{ item.url }}" class="cart__product-title" data-cart-item-title>
{{ item.product.title }}<br>
{% assign property_size = item.properties | size %}
{% if property_size > 0 %}
{% for p in item.properties %}
{{ item.properties.count }}
{% assign first_character_in_key = p.first | truncate: 1, '' %}
{% unless p.last == blank or first_character_in_key == '_' %}
{{ p.first }}:
{% if p.last contains '/uploads/' %}
<a class="lightbox" href="{{ p.last }}">{{ property_size }}</a>
{% else %}
{{ p.last }}
{% endif %}
<br>
{% endunless %}
{% endfor %}
{% endif %}
</a>
</div>
问题是即使我上传了两张或更多图片,property_size 变量的值为 1,而实际上我应该 return 项目具有的属性数量。 谁能帮帮我吗?我做错了什么?
本教程上传后,Debut 主题可能已更改,并且由于不受支持,可能不会更新。
如果您添加 type="text"
输入而不是 type="file"
,则会按预期添加 属性。发生这种情况是因为 _initAddToCart
函数(assets/theme.js
行 6447)获取表单 HTML 元素并将其传递给另一个函数。
var $data = $(this.selectors.productForm, this.$container);
this._addItemToCart($data);
然后在_addItemToCart
函数中(assets/theme.js
行6513),形式是serialized转成一个字符串:
var params = {
url: '/cart/add.js',
data: $(data).serialize(),
dataType: 'json',
};
$.post(params).done(...
此函数将忽略文件输入,如 jQuery 文档中所述:
Data from file select elements is not serialized.
要发送文件,必须设置FormData browser API can be used. But to use it with the jQuery AJAX call, some properties:
var params = {
url: '/cart/add.js',
// data: $(data).serialize(),
dataType: 'json',
// Disable the jQuery data processing, and send the FormData object
contentType: false,
processData: false,
data: new FormData($(data).get()[0])
};
$.post(params).done(...
但是,由于 HTML 文件 <input>
有 name="properties[Photo]"
,只有最后一个上传的文件会被添加到购物车项目的 Photo
属性.
我尝试使用 name="properties[Photo][]"
,但 cart/add.js
仅调用 returns 错误 500 并显示消息 "Internal Server Error".
因此,要上传多个文件,您可以将一些自定义代码添加到 _addItemToCart
函数中,让每个 File from the <input>
and add to the FormData 每个文件都有不同的密钥。