🍎

ShopifyカートAPIを使ってみよう②

2024/05/09に公開

以前の記事ではShopifyのカートAPIを使用した商品の追加方法を説明しましたが、今回はカートページ内でアイテムを削除した時の動作を綺麗に動かす方法を説明して行きます。

実践

まずはカートページにフォームを用意します。
商品名、個数、小計、合計、削除ボタンがあるシンプルなフォームです。

main-cart.liquid
<form action="{{ routes.cart_url }}" id="cart_form" class="cart__contents critical-hidden" method="post" id="cart">
    {%- if cart != empty -%}
      {%- for item in cart.items -%}
        <div class="cart-item" data-key="{{ item.key }}">
          <dl>
            <dt>商品名</dt>
            <dd>{{ item.title }}</dd>
          </dl>
          <dl>
            <dt>個数</dt>
            <dd>
                {{ item.quantity }}
            </dd>
          </dl>
          <dl>
            <dt>小計</dt>
            <dd>
              <div class="cart-item-total">
                <span class="line-item-price">
                    {{ item.final_line_price | money }}
                </span>
              </div>
            </dd>
          </dl>
          <dl>
            <dt>削除</dt>
            <dd>
              <div clas="cart-item-remove">
                <a class="remove-item" href="{{ item.url_to_remove }}">
                  アイテム削除
                </a>
              </div>
            </dd>
          </dl>
        </div>
      {% endfor %}
    {% else %}
      <p>商品がありません</p>
    {% endif %}
  </form>

この状態でも削除ボタンは動作しますがリダイレクトが発生し、少し不便です。
そのため以下のようなscriptを書いて行きます。

cart
  document.querySelectorAll(".remove-item").forEach( (remove)=> {
    remove.addEventListener("click", (e) => {
      e.preventDefault();

      const item = remove.closest(".cart-item");
      const key = item.getAttribute('data-key');

     let data = {
       items: [{
         id: key,
         quantity: 0,
       }]
     };
     // 追加
     fetch('/cart/change.js', {
       method: 'POST',
       headers: {
         'Content-Type': 'application/json'
       },
       body: JSON.stringify(data)
      }).then(res => {
        if(res.data.items.length === 0) {
          document.querySelector("#cart_form").remove();

          const html = document.createElement('div');
          html.innerHTML = `
            <h1>cart</h1>
            <div class="cart-empty">
              <p>カートの空です</p>
            </div>
          `

          document.querySelector('.cart .width').appendChild(html);
          
        }else{
          // 割引金額
          const totalDiscount = res.data.total_discount;
          document.querySelector('#total-discount').textContent = totalDiscount;

          // 合計金額
          const totalPrice = res.data.total_price;
          document.querySelector('#total-price').textContent = totalPrice;

          item.remove();
        }
      }).then(() => {
        // 削除後の合計数を取得
        axios("/cart.js")
        .then(res => {
          console.log(res)  ;
          document.querySelector('#total_count').textContent = res.data.item_count;
        })
      });
    })
  })

解説

今回はカートAPIのchange.jsを使用します。
削除するだけのでquantityは0で大丈夫です。

https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-change-js

cart
const item = remove.closest(".cart-item");
const key = item.getAttribute('data-key');

let data = {
  items: [{
    id: key,
    quantity: 0,
  }]
};
// 追加
fetch('/cart/change.js', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
})

APIを取得できたらカート全体の割引金額と合計金額を取得し反映した後、アイテムを削除します。

cart
  // 割引金額
  const totalDiscount = res.data.total_discount;
  document.querySelector('#total-discount').textContent = totalDiscount;

  // 合計金額
  const totalPrice = res.data.total_price;
  document.querySelector('#total-price').textContent = totalPrice;

  item.remove();

最後にカート全体の合計数をAPIで取得して反映することで、
アイテムが削除され、合計値とアイテム合計数が更新される一連の流れをリダイレクトを発生させずに動作させることができました。

cart
// 削除後の合計数を取得
axios("/cart.js")
.then(res => {
  console.log(res)  ;
  document.querySelector('#total_count').textContent = res.data.item_count;

注意点

APIで取得した合計金額や割引金額は設定された金額フォーマットが適応されてないので数字の羅列になっています。もう人手間加える必要性がありますが長くなるので次の記事で紹介します。

Discussion