Liquid Snippets by ALSEL
🛒 カート/チェックアウト中級

カート内の商品一覧

カートに入っている商品を行ごとに表示し、数量変更・削除・割引情報の表示に対応するスニペット。カートが空のときは空カートメッセージを表示する。

用途
カートドロワーやカートページで、ユーザーが追加した商品の詳細(バリアント、数量、割引、カスタムプロパティ)を一覧表示するときに使う。
設置場所
snippets/cart-items.liquid に配置し、cart.liquid または cart-drawer.liquid などのカート表示セクション内で `{% render 'cart-items' %}` で呼び出す。
注意点
数量入力フィールドの `data-line-item-key` 属性は後段の JavaScript で AJAX 更新をトリガーするため、form name="updates[]" 内に配置されている前提がある。カスタムプロパティ(line_item.properties)のキーが `_` で始まるものはシステム用として非表示にするため、フロントエンドで見せたくないデータはキー名の先頭に `_` を付ける。バリアント・サブスクリプション販売プラン・割引情報は対応していない場合は `empty` チェックで条件分岐しているため、管理画面で有効になっていない場合は自動的に非表示になる。
タグ:cartline-itemquantitydiscountvariantselling-plan

コード

118 行 / liquid
{% if cart.items == empty %}
  <div class="cart-empty pt-10 pb-12 text-center">
    {% render 'svg-icons', icon: 'cart', class: 'mb-3' %}
    {{ 'cart.empty_html' | t }} 
    <button class="btn btn-outline-primary" type="button" data-bs-dismiss="offcanvas">
      {{ 'cart.continue_shopping' | t }}
    </button>
  </div>
{% else %}
  <ul 
    class="cart-items-list list-unstyled mb-6 border-bottom-1" 
    aria-label="{{ 'general.accessibility.cart_items' | t }}">
    {% for line_item in cart.items %}
      <li class="cart-item py-3">
        <div class="row mx-n3 align-items-center">
          <div class="col-6 px-3">
            <a href="{{ line_item.url }}" tabindex="-1">
              {% render 'image-url', img: line_item.image, orientation: settings.product_card_img_orientation, class: settings.product_card_img_border %}
            </a>
          </div>
          <div class="col-12 px-3 position-relative">
            <div class="me-10">
              <h3 class="cart-item-product-title h6 mb-1">
                <a href="{{ line_item.url }}" class="link-dark text-decoration-none">
                  {{ line_item.product.title }}
                </a>
              </h3>
              {% unless line_item.product.has_only_default_variant %}
                <p class="cart-item-variant-title d-block opacity-70 mb-1 small">
                  {{ line_item.variant.title }}
                </p>
              {% endunless %}
              {% unless line_item.selling_plan_allocation == empty %}
                <p class="cart-item-selling-plan d-block opacity-70 mb-1 small">
                  {{ line_item.selling_plan_allocation.selling_plan.name }}
                </p>
              {% endunless %}
              {% unless line_item.properties == empty %}
                <ul class="cart-item-properties list-unstyled opacity-70 small mb-1">
                  {% for property in line_item.properties %}
                    {% assign first_character_in_key = property.first | slice: 0 %}
                    {% unless first_character_in_key == '_' %}
                      <li>
                        {% if property.last contains 'https' %}
                          {{ property.first }}: 
                          <a href="{{ property.last }}" target="_blank">
                            {{ 'cart.property_view_file' | t }}
                          </a>
                        {% else %}
                          {{ property.first }}: {{ property.last }}
                        {% endif %}
                      </li>
                    {% endunless %}
                  {% endfor %}
                </ul>
              {% endunless %}
              {% if line_item.line_level_discount_allocations.size > 0 %}
                <ul 
                  class="cart-item-discounts list-unstyled fs-xs mb-1 alert alert-primary py-2 px-3" 
                  aria-label="{{ 'cart.applied_discounts' | t }}">
                  {%- for discount in line_item.line_level_discount_allocations -%}
                    <li class="">
                      {% render 'svg-icons', icon: 'tag', size: 12, class: 'me-1' %}
                      {{ discount.discount_application.title }}
                    </li>
                  {%- endfor -%}
                </ul>
              {% endif %}
            </div>
            <div class="d-flex align-items-center justify-content-between pt-4">
              <div class="qty-input-wrapper me-3" role="group" aria-label="{{ 'general.accessibility.quantity' | t }}">
                <button 
                  class="btn btn-qty-minus"
                  type="button"
                  onclick="--this.nextElementSibling.value, this.nextElementSibling.dispatchEvent(new Event('change'))" 
                  aria-label="{{ 'general.accessibility.decrease_qty' | t }}">
                  {% render 'svg-icons', icon: 'minus', size: 14 %}
                </button>
                <input
                  class="form-control form-control-sm" 
                  name="updates[]"
                  type="number"
                  value="{{ line_item.quantity }}"
                  min="0"
                  aria-label="{{ 'product.quantity' | t }}"
                  data-line-item-key="{{ line_item.key }}">
                <button 
                  class="btn btn-qty-plus"
                  type="button"
                  onclick="++this.previousElementSibling.value, this.previousElementSibling.dispatchEvent(new Event('change'))" 
                  aria-label="{{ 'general.accessibility.increase_qty' | t }}">
                  {% render 'svg-icons', icon: 'plus', size: 14 %}
                </button>
              </div>
              <p class="cart-item-price text-end lh-sm mb-0">
                {% if line_item.original_line_price > line_item.final_line_price %}
                  <s class="product-price-compare small opacity-70 me-2">
                    {{ line_item.original_line_price | money }}
                  </s>
                {% endif %}
                <span class="cart-item-price-final">
                  {{ line_item.final_line_price | money }}
                </span>
              </p> 
            </div>
            <button 
              class="btn btn-line-item-remove btn-icon position-absolute top-0 end-0 mt-n4 me-n1"
              type="button"
              data-line-item-key="{{ line_item.key }}"
              aria-label="{{ 'general.accessibility.remove' | t }}">
              {% render 'svg-icons', icon: 'remove', size: 16 %}
            </button>
          </div>
        </div>
      </li>
    {% endfor %}
  </ul>
{% endif %}

出典・ライセンス

License:
MIT

このコードは kondasoft 著作の MIT ライセンスソースです。 原本の著作権は kondasoft が保有します。日本語訳は ALSEL によるものです。

関連項目

🛒 カート/チェックアウト中級

カートドロワー

Shopify の Bundled Section Rendering に対応したカートドロワーセクション。カート更新時に動的にフェッチされ、AJAX で自動的に再レンダリングされる。

📁 ks-bootshop·MIT·6
🛒 カート/チェックアウト中級

カート件数バッジ

カート内の商品件数を表示するバッジを、Shopify の Bundled section rendering 機能で動的に更新する。カート更新時に AJAX で再レンダリングされ、常に最新の件数を表示。

📁 ks-bootshop·MIT·6
🛒 カート/チェックアウト中級

カートドロワー

ページ右側からスライドインするオフキャンバスカートドロワー。商品一覧、メモ機能、フッター情報を1つのコンテナで管理し、アップセル機能にも対応する。

📁 ks-bootshop·MIT·32
🛒 カート/チェックアウト初級

カート注文備考欄

カートページに注文時の備考を記入できるテキストエリアを開閉形式で表示する。テーマ設定で有効化するとカート内容がある場合のみ表示され、JavaScript で自動保存機能に対応する。

📁 ks-bootshop·MIT·37
🛒 カート/チェックアウト初級

カートフッターの割引・小計・チェックアウト

カートドロワーの下部に割引適用状況、小計、チェックアウトボタンを表示するスニペット。適用割引があれば金額と共に一覧表示し、セール価格と定価の二重表示にも対応する。

📁 ks-bootshop·MIT·45
🛒 カート/チェックアウト初級

カートページの商品一覧

ショッピングカートの内容を一覧表示し、各商品の数量変更と削除機能を提供するテンプレート。カート内の商品数が0の場合は空カート表示、それ以外は商品ごとに画像・タイトル・価格・数量入力欄を出す。

📁 liquid·MIT·67