FROM CACHE - jp_header

Re: カートページへ「配送日時指定」機能の実装(上手く動作しない)

カートページへ「配送日時指定」機能の実装(上手く動作しない)

s_yamaoka
Shopify Partner
15 0 1

カートページへ「配送日時指定」機能の実装を試みていますが、上手く動作しません。

 

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 }}&amp;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 }}&nbsp;</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件の返信1

Qcoltd
Shopify Partner
1076 442 436

質問からで恐縮ですが、

質問者様の状況はどちらになりますか?

 

  1. 質問内容に記載いただいた状態で、カートは正常に機能しているのに、cart attributesが注文に反映されない。
  2. {% render 'date-picker' %} を質問内容に記載いただいた場所以外に記載すると、cart attributesが反映されない。

 

「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を組まれるとうまくいくのではないかと思います。

 

状況が把握できていないためフワフワした回答で恐縮ですが、

参考になれば幸いです。

(キュー田辺)

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/