Liquid、JavaScriptなどに関する質問
カートページへ「配送日時指定」機能の実装を試みていますが、上手く動作しません。
Datepickerのカレンダーが上手く表示されません。
別のセクションなどに、「snippet/date-picker.liquid」を埋め込むと、カレンダーが表示されますが、当然「cart.attributes」が管理画面へ反映されません。
恐縮ですが、アドバイス頂けますと大変嬉しいです。
snippet/cart-form.liquid↓
<form class="ajax-cart__cart-form grid__wrapper edge js-cart-form {{ formEmpty }}" action="{{ routes.cart_url }}" method="post"> {% render 'date-picker' %} <div class="ajax-cart__cart-items span-12 auto"> {% for item in cart.items %} <ul class="item_{{ item.id | append: '-' | append: forloop.index }} ajax-cart__cart-item grid__wrapper edge"> <a class="ajax-cart__item-remove--no-js" style="display:none;" href="/cart/change?line={{ forloop.index }}&quantity=0" data-role="product-remove"> {% render 'snip-icons', wrapper: '.ajax-cart__item-remove--no-js', type: 'apollo', icon: 'close', classes: 'ajax-cart__item-remove--icon', size: '10px', fill: 'var(--text-color)', hover: 'var(--text-color)' %} </a> <li class="remove_{{ item.id | append: '-' | append: forloop.index }} ajax-cart__item-remove mb0 js-cart-remove" {% if no_js_cart %}style="display: none;"{% endif %} data-item-id="{{ item.id | append: '-' | append: forloop.index }}" data-item-key="{{ item.key }}" data-line-item="{{ forloop.index }}"> {% render 'snip-icons', wrapper: '.ajax-cart__item-remove', type: 'apollo', icon: 'close', classes: 'ajax-cart__item-remove--icon', size: '10px', fill: 'var(--text-color)', hover: 'var(--text-color)' %} </li> <li class="ajax-cart__item-image v-start"> <div class="ajax-cart__item-image__wrapper"> <a href="{{ item.url }}" title="{{ item.product.title | escape }}"> {% if item.image != blank %} {% render 'basic-responsive-image', type: item.image, width: 1200 %} {% else %} {{ 'product-1' | placeholder_svg_tag: 'placeholder-svg' }} {% endif %} </a> </div> </li> <li class="ajax-cart__item-details v-center"> <div class="ajax-cart__cart-title__wrapper inline-block v-center"> <p class="ajax-cart__title"><a href="{{ item.product.url }}">{{ item.product.title }}</a></p> <div class="ajax-cart__cart-variants"> {% if item.selling_plan_allocation %} <p>{{ item.selling_plan_allocation.selling_plan.name }}<p> {% endif %} {%- unless item.variant.title contains 'Default' -%} {% for option in item.product.options %} <strong>{{ option }}:</strong> {{ item.variant.options[forloop.index0] }}<br/> {% endfor %} {%- endunless -%} {% assign property_size = item.properties | size %} {% if property_size > 0 %} <p> {% for p in item.properties %} {% unless p.last == blank %} <strong>{{ p.first }}:</strong> {% comment %} Check if there was an uploaded file associated {% endcomment %} {% if p.last contains '/uploads/' %} <a href="{{ p.last }}">{{ p.last | split: '/' | last }}</a> {% else %} {{ p.last }} {% endif %} <br> {% endunless %} {% endfor %} </p> {% endif %} </div> </div> </li> <li class="ajax-cart__item-price v-center"> {%- assign hasDiscount = false -%} {%- if item.original_price != item.final_price -%} {%- assign hasDiscount = true -%} {%- endif -%} <div data-cart-item-price> <dl data-cart-item-price-list> {%- comment -%} Markup template for discount item {%- endcomment -%} <div {% unless hasDiscount %}class="hide" {% endunless %}data-cart-item-discounted-price-group> <dt> <span class="visually-hidden">{{ 'products.general.regular_price' | t }}</span> </dt> <dd> <s data-cart-item-original-price>{{ item.original_price | money }}</s> </dd> <dt> <span class="visually-hidden">{{ 'products.general.sale_price' | t }}</span> </dt> <dd> <span class="order-discount onsale" data-cart-item-final-price>{{ item.final_price | money }}</span> </dd> </div> {%- comment -%} Markup template for regular price item {%- endcomment -%} <div {% if hasDiscount %}class="hide" {% endif %}data-cart-item-regular-price-group> <dt> <span class="visually-hidden">{{ 'products.general.regular_price' | t }}</span> </dt> <dd data-cart-item-regular-price> {{ item.original_price | money }} </dd> </div> {%- comment -%} Markup template for unit price {%- endcomment -%} <div {% unless item.unit_price_measurement %}class="hide" {% endunless %}data-unit-price-group> <dt> <span class="visually-hidden visually-hidden--inline">{{ 'products.product.unit_price_label' | t }}</span> </dt> <dd> <span class="price-unit-price"> {%- capture unit_price_separator -%} <span aria-hidden="true">/</span><span class="visually-hidden">{{ 'general.accessibility.unit_price_separator' | t }} </span> {%- endcapture -%} {%- capture unit_price_base_unit -%} {%- if item.unit_price_measurement.reference_value != 1 -%} {{- item.unit_price_measurement.reference_value -}} {%- endif -%} {{ item.unit_price_measurement.reference_unit }} {%- endcapture -%} <span data-unit-price>{{ item.unit_price | money }}</span>{{- unit_price_separator -}}<span data-unit-price-base-unit>{{- unit_price_base_unit -}}</span> </span> </dd> </div> </dl> </div> {%- assign itemDiscounts = 'template ' | split: ' ' -%} {%- if item.line_level_discount_allocations != blank -%} {%- assign itemDiscounts = item.line_level_discount_allocations -%} {%- endif -%} <ul class="ajax-cart__order-discount mb0 order-discount--list order-discount--title order-discount--cart{% if item.line_level_discount_allocations == blank %} hide{% endif %}" aria-label="{{ 'customer.order.discount' | t }}" data-cart-item-discount-list> {%- for discount_allocation in itemDiscounts -%} <li class="order-discount__item" data-cart-item-discount> <p class="onsale"> {% render 'snip-icons', wrapper: '.order-discount__item', type: 'apollo', icon: 'sale-tag', classes: 'vi-center', size: '10px', fill: 'var(--sale-color)', hover: 'var(--sale-color)' %} <span class="vi-center sale-color" data-cart-item-discount-title> {{- discount_allocation.discount_application.title -}} </span> (-<span data-cart-item-discount-amount>{{ discount_allocation.amount | money }}</span>) </p> </li> {%- endfor -%} </ul> </li> <li class="ajax-cart__item-qty v-center js-item-quantity"> <div class="ajax-cart__item-quantity a-left"> <button data-ajax-qty-decrease="{{ item.id | append: '-' | append: forloop.index }}" data-item-key="{{ item.key }}" class="downer-{{ item.id | append: '-' | append: forloop.index }} ajax-cart__qty-control--down mb0 v-center" type="button"><span class="visuallyhidden">{{ 'cart.general.decrease' | t: product: item.title | escape }}</span>-</button> <input class="updates_{{ item.id | append: '-' | append: forloop.index }} {% if no_js_cart %}ajax-cart__qty-input--no-js{% else %}ajax-cart__qty-input{% endif %} v-center a-center" data-item-qty data-item-id="{{ item.id | append: '-' | append: forloop.index }}" data-item-key="{{ item.key }}" data-item-line="{{ forloop.index }}" type="number" name="updates[]" value="{{ item.quantity }}" min="0" data-limit="{% if item.variant.inventory_management == 'shopify' %}{% unless item.variant.inventory_policy == 'continue' %}{{ item.variant.inventory_quantity }}{% endunless %}{% endif %}" /> <button data-ajax-qty-increase="{{ item.id | append: '-' | append: forloop.index }}" class="up-{{ item.id | append: '-' | append: forloop.index }} ajax-cart__qty-control--up mb0 v-center" type="button"><span class="visuallyhidden">{{ 'cart.general.increase' | t: product: item.title | escape }}</span>+</button> </div> <input class="ajax-cart__item-update--no-js button-as-link" type="submit" name="update" style="display:none;" value="{{ 'cart.general.update' | t }}"> </li> <li class="ajax-cart__item-line-price v-center"> <dl {% unless item.original_line_price != item.final_line_price %}class="hide" {% endunless %}data-cart-item-discounted-price-group> <dt> <span class="visually-hidden">{{ 'cart.label.regular_total' | t }}</span> </dt> <dd> <s data-cart-item-original-price>{{ item.original_line_price | money }}</s> </dd> <dt> <span class="visually-hidden">{{ 'cart.label.discounted_total' | t }}</span> </dt> <dd> <span class="order-discount onsale" data-cart-item-final-price>{{ item.final_line_price | money }}</span> </dd> </dl > <div {% if item.original_line_price != item.final_line_price %}class="hide" {% endif %}data-cart-item-regular-price-group> <span data-cart-item-regular-price>{{ item.original_line_price | money }}</span> </div> </li> </ul> {% endfor %} </div> <div class="ajax-cart__info-wrapper a-left {% if cart.item_count < 1 %}hide{% endif %} js-cart-info"> <ul class="ajax-cart__accordion js-cart-accordion"> {% if settings.show_cart_notes %} <li class="tlink has_sub_menu closed"> <a class="closed" aria-haspopup="true" aria-expanded="false" href="">{{ 'cart.general.note' | t }}</a> <span class="icon inactive-arrow">+</span> <span class="icon active-arrow">-</span> </li> <ul class="accordion-content sub closed"> <div class="a-left"> <label class="visuallyhidden" for="note">{{ 'cart.general.note' | t }}</label> <textarea name="note" id="note" rows="5" cols="60" class="js-cart-note">{{ cart.note }}</textarea> </div> </ul> {% endif %} {% if settings.show_shipping_calculator %} <li class="tlink2 has_sub_menu closed ajax-cart__accordion--shipping-calc"> <a class="closed" aria-haspopup="true" aria-expanded="false" href="">{{ 'cart.general.calc_heading' | t }}</a> <span class="icon inactive-arrow">+</span> <span class="icon active-arrow">-</span> </li> <ul class="accordion-content2 sub closed"> {% render 'cart-shipping-calculator', cart %} </ul> {% endif %} </ul> {% if settings.show_shipping_countdown %} <div class="ajax-cart__free-shipping"> {% render 'cart-shipping-countdown', cart %} </div> {% endif %} </div> <div class="ajax-cart__summary-wrapper {% if cart.item_count < 1 %}hide{% endif %} js-cart-summary"> <div class="ajax-cart__final-details"> <div class="subtotal"> <p class="title a-left mb0">{{ 'cart.general.subtotal' | t }}</p> <p class="subtotal-price a-right mb0"><span class="cart-original-total cart-price block js-cart-subtotal">{{ cart.items_subtotal_price | money }}</span></p> </div> {%- if settings.show_tax_note -%} <div class="tax"> <p class="title a-left mb0">{{ 'cart.general.tax' | t }}</p> <p class="a-right mb0">{{ 'cart.general.at_checkout' | t }}</p> </div> {%- endif -%} {%- if settings.show_shipping_note -%} <div class="shipping"> <p class="title a-left mb0">{{ 'cart.general.shipping' | t }}</p> <p class="a-right mb0">{{ 'cart.general.at_checkout' | t }}</p> </div> {%- endif -%} <div class="discounts"> {%- if cart.cart_level_discount_applications != blank -%} <p class="a-left">{{ 'cart.general.discounts' | t }}</p> <ul class="a-right"> {%- for discount_application in cart.cart_level_discount_applications -%} <li> {% render 'snip-icons', wrapper: '.discounts', type: 'apollo', icon: 'sale-tag', classes: 'vi-center', size: '10px', fill: 'var(--sale-color)', hover: 'var(--sale-color)' %} <span class="vi-center sale-color">{{ discount_application.title }}(-{{ discount_application.total_allocated_amount | money }})</span> </li> {%- endfor -%} </ul> {%- else -%} {% if cart.total_discounts > 0 %} <div class="cart_savings onsale"> <p class="a-left"><em>{{ 'cart.general.savings' | t }}</em></p> <p class="cart-savings-amount a-right"><em>{{ cart.total_discounts | money }}</em></p> </div> {% endif %} {%- endif -%} </div> <hr /> <div class="total"> <p class="title a-left">{{ 'cart.general.total' | t }}</p> <p class="total-price a-right"><span class="cart-original-total cart-price block">{{ cart.total_price | money }}</span> <span class="cart-total"></span></p> </div> </div> <div class="ajax-cart__buttons"> <a class="ajax-cart__button-view_cart button secondary-button" href="{{ routes.cart_url }}">{{ 'products.product.view_cart' | t }}</a> <input class="ajax-cart__button-submit" type="submit" name="checkout" id="checkout" value="{{ 'cart.general.checkout' | t }}" /> {%- unless request.design_mode -%} {% if additional_checkout_buttons %} <p class="sm-caps or-divider mt2 mb2 a-center"><span>Or</span></p> <div class="ajax-cart__buttons-additional"> {{ content_for_additional_checkout_buttons }} </div> {% endif %} {%- endunless -%} </div> </div> </form>
snippet/date-picker.liquid↓
{% comment %} /**配送日時の指定**/ {% endcomment %} <div style="width:200px; margin: 20px auto 20px 0;"> <span style="display:block; margin-bottom: 5px;">配送希望日</span> <input type="radio" name="attributes[配送日指定の有無]" value="指定しない" id="datePicker__label--false" {% unless cart.attributes["配送指定の有無"] == "指定する" %} checked{% endunless %}> <label for="datePicker__label--false">指定しない</label> <input type="radio" name="attributes[配送日指定の有無]" value="指定する" id="datePicker__label--true" {% if cart.attributes["配送指定の有無"] == "指定する" %} checked{% endif %}> <label for="datePicker__label--true">指定する</label> <input id="datepicker" type="text" name="attributes[配送希望日]" value="{{ cart.attributes.date }}" placeholder="配送希望日を選択する" readonly disabled/> </div> <div style="width:200px; margin: 20px auto 20px 0;"> <span style="display:block; margin-bottom: 5px;">配送希望時間帯</span> <select id="delivery-time" name="attributes[配送希望時間帯]"> <option value="指定なし" {% if cart.attributes["配送希望時間帯"] == "指定なし" %} selected{% endif %}>指定なし</option> <option value="午前中" {% if cart.attributes["配送希望時間帯"] == "午前中" %} selected{% endif %}>午前中</option> <option value="14時から16時" {% if cart.attributes["配送希望時間帯"] == "14時から16時" %} selected{% endif %}>14時から16時</option> <option value="16時から18時" {% if cart.attributes["配送希望時間帯"] == "16時から18時" %} selected{% endif %}>16時から18時</option> <option value="18時から20時" {% if cart.attributes["配送希望時間帯"] == "18時から20時" %} selected{% endif %}>18時から20時</option> <option value="19時から21時" {% if cart.attributes["配送希望時間帯"] == "19時から21時" %} selected{% endif %}>19時から21時</option> </select> </div> <script> //土日祝日指定 $.get("https://holidays-jp.github.io/api/v1/date.json", function(holidaysData) { $("#datepicker").datepicker({ minDate: '+3D', maxDate: '+5M', beforeShowDay: function(date) { if (date.getDay() == 0) { return [false, 'day-sunday', null];//trueで土曜日を選択可に変更 } else if (date.getDay() == 6) { return [false, 'day-saturday', null];//trueで日曜日を選択可に変更 } var holidays = Object.keys(holidaysData); for (var i = 0; i < holidays.length; i++) { var holiday = new Date(Date.parse(holidays[i])); if (holiday.getYear() == date.getYear() && holiday.getMonth() == date.getMonth() && holiday.getDate() == date.getDate()) { return [false, 'day-holiday', null];//trueで祝日を選択可に変更 } } return [true, 'day-weekday', null]; } }); }); //配送指定がない場合に配送希望日を選択できないようにする $(function(){ $( 'input[name="attributes[配送日指定の有無]"]:radio' ).change( function() { var radioval = $(this).val(); if(radioval == "指定する"){ $('#datepicker').removeAttr('disabled'); }else{ $('#datepicker').attr('disabled','disabled').val(""); } }); }); </script>
質問からで恐縮ですが、
質問者様の状況はどちらになりますか?
「1」の状況の場合、
実際にサイトを拝見してみないと原因は分からなさそうです。
記載いただいたコードのうち、inputやselectのみを私の開発環境のcartページに埋め込んでみましたが、注文情報にcart attributesが問題なく渡されましたので、質問者様の環境で動かないのは、使用されいているテーマの影響(JSの影響?)である可能性が高く、ページ全体を見てみないとこれ以上調査のしようがなさそうでした。
「2」の状況の場合、
さらに2つに分岐するのですが、
cartのform要素があるページにて、form要素の外にinput要素やselect要素を設置する場合は、
form要素にid="cart"とつけ、
input要素やselect要素に、form="cart"とつければ、
うまくいかないでしょうか?
そうではなく、
cartのform要素が存在しないページに、
cart attributesのためのinput要素やselect要素を設定する場合は、
https://shopify.dev/docs/api/ajax
こちらのページなどを参考に、
JavaScriptを組まれるとうまくいくのではないかと思います。
状況が把握できていないためフワフワした回答で恐縮ですが、
参考になれば幸いです。
(キュー田辺)
Shopifyの請求書の支払いが失敗したという通知を受け取って驚いたことはありますか。初めての支払いでエラーが発生したり、これまで何の問題もなく支払いできていたのに突然失敗し...
By Minami_ Sep 8, 20242023年2月、Shopifyはcheckout.liquidを廃止し、Checkout Extensibilityに移行することを発表いたしました。この新しいチェックアウト...
By JasonH Aug 15, 2024「味噌の可能性を、とき放つ」をコンセプトに、豊かな自然に恵まれた信州で味噌の製造販売を行う新田醸造。江戸末期に創業した老舗のみそ屋さんですが、2024年春、顧客層や販売範囲の...
By Minami_ Jul 30, 2024