Shopifyではデザインが洗練されたテーマを使用すれば、カートページのデザインもイケてるものにできるはず、、と思いきや、何もしないと案外UIが悪いものがある。
ここでは、カートページ内を一新した例をもとに要点を紹介します。
商品ページ、カートページでは、<form>タグや<input>タグの使い方やテーマのコアになるjsの仕様をよく理解していないといけないし、ECサイトが機能しないことになりますので、クリティカル・取扱注意なコードである。
今回はその中のカートページのカスタマイズについて。
カートページカスタマイズの際の要点
ノーコード(ノーコーディング)では構造の自由度がないため、コーディングが必要になる。
ノーコードの場合の構図の例
以下のように、
- 備考欄(配送メモ欄)と配送希望日の位置がそれぞればらばらになる。
- テーマによっては数量選択のUIがプルダウンになっているので、数量増減には2クリックが必要(①プルダウンを開く②数を選択する)になる。
コーディングで構図を整えた場合の例
- 備考欄(配送メモ欄)と配送希望日の位置が整理され情報が一目瞭然。
- 数量選択がーと+のスピナーボタンになっているので、ユーザはワンクリックで増減ができる。
補足:セクションでもブロックでもざっくりはノーコードで組み込みできる
※Dawnはセクション単位で機能が分割されていたため、ノーコードでも構図を組み替えることができた。Dawn優秀。。ただし備考欄を表示する機能がない!
数量選択スピナーを作成する
UIとしてはプルダウンよりスピナーの方が手数がかかって大変です。
以下のような仕様を想定します。
- ーか+ボタンを作成し、それぞれクリックされた時の挙動を作り分ける
- 数量が変更されたとき、合計金額が自動更新されるようにjsでCart APIを使用する
それぞれ実装方法を順に解説します。
スピナーボタンの作成:ーか+ボタンを作成し、それぞれクリックされた時の挙動を作り分ける
イケてない場合の構図の例
コーディングでスピナーをつけた場合の例
- input内の数値をスピナーで変更できるようにjsを記述
- スピナーでinput内の数値を変更した際に、合計金額が動的に変わるようにテーマのjsに追記することを忘れず!
snippetに以下ふたつのファイルを追加する
icon-mimus.liquid
(コード)
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash" viewBox="0 0 16 16">
<path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/>
</svg>
icon-plus.liquid
(コード)
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg>
余談:ありそうでなかなかない、無料SVGの素材サイト(だいたいどこも本当に使えるやつは有料にしている)
-と+のくせのないSVGアイコン画像がほしい。
だが、これが意外にも、簡単に見つからない。妙な素材サイトばかり見つかり、SVGコードを知りたければPro版を促され、課金を要求されるところが多い。そんなすさんだ世の中で、一閃の光が。。
それがこちらです。
(一時期はfontawesome使ったりしたこともあったけど、
あっちも無料だともっさりしたデザインのを使わされる形なのと、
あと意外と読み込みが重い。。
初めはよかったが、ページスピードを気にしていると、fontawesomeの部分だけが後出しで出てくるような表示になりイケてなかった)
スピナーボタンに数量増減のボタン機能をつける
スピナーのliquid
( さきほど作ったicon-minus.liquidとicon-plus.liquidのスニペットを{% render ‘icon-minus’ %}および{% render ‘icon-plus’ %}で呼び出して( 表示して )います。
<button class="quantity__button btnspinner spinner-down" name="minus" type="button" item_index="{{ item_index }}">
{% render 'icon-minus' %}
</button>
<!--ここにもとの数値入力フォーム(セレクトボックス式)-->
<button class="quantity__button btnspinner spinner-up" name="plus" type="button" item_index="{{ item_index }}">
{% render 'icon-plus' %}
</button>
js
//数量スピナーボタン(マイナス)
$('.spinner-down').on('click', function () {
let current_qty = parseInt($(this).nextAll('input').val());
let change_qty = current_qty - 1;
$(this).nextAll('input').attr("value", change_qty);
var item_index = $(this).attr("item_index");
lineitemQuantity( item_index, change_qty )
});
//数量スピナーボタン(プラス)
$('.spinner-up').on('click', function () {
let current_qty = parseInt($(this).prevAll('input').val());
let change_qty = current_qty + 1;
$(this).prevAll('input').attr("value", change_qty);
var item_index = $(this).attr("item_index");
lineitemQuantity( item_index, change_qty )
});
数量変更時の合計金額自動更新の処理:CartAPIを利用してjsを追記
こちらが公式から解説しているCart APIの仕様。
ちょっと翻訳版を一読してみてほしいのだが、僕はこれを読んで、何度も
「で、結論コードは何て書けばいいの??」でした。
どうやら、jsの構文のfetch〜thenを用いて、上記リファレンスで解説しているパラメータをfetchに続けて以下のように読む必要があったようです。
fetch("/cart/change", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(
{
line: line,
quantity: quantity
}),
postのbodyでvariantID( ここではline )を渡しているが、他にも line item key でもいけるようだ。
作成したjsに以下を追記する。
function lineitemQuantity (line, quantity){
var quantity = quantity;
fetch("/cart/change", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(
{
line: line,
quantity: quantity
}),
}).then(() => {
location.reload();
});
fetch(“/cart/change”からはじまる構文で、Cart APIの”changeイベント”を呼ぶ処理をしている。
テーマのコアjs(例えばtheme.jsのような名前か、テーマ名”Empire”の場合はempire.jsのように命名されていることが多い)の中に、
カートページの数量入力の前後にマイナスとプラスのスピナーを設置したためボタン押下時に金額が更新されるようにするコードを追記。
個人的にはここの挙動を精査するのが一番しんどかった。
this.$el.on(‘click.cart-page’
とか、
this.$el.on(‘change.cart-page’
で検索したらヒットする行があれば、その下に以下を追記。
this.$el.on('click.cart-page', '[btnspinner]', this._editItemQuantity);
カートページの数量入力の前後に、さきほど作成したマイナスとプラスのスピナーボタン押下時に金額が更新されるようにするコードだ。
前後で使用されている変数に合わせて改変すること!
ここでは、
[btnspinner]
で、スピナーボタンにつけた属性名を指定している。
以上です!
これでカートページ改修のときの一番の悩みは解消できるのではないでしょうか?
追記:jsにコードを追加して、数量上限設定を行う!
上記のjsだけでは数量を無限に(1,000でも10,000でも)入れられてしまいますので、上限の設定をする必要があったので、jsで制御する必要がありました。
以下のコードで、入力フォームがすでに0のときにはそれ以上マイナスにならないようにし、
プラスを連打しても5以上にならないような制御を入れています。
ストアによっては、さらに細かく、「Aというグループの商品は小型サイズだから10個までカートインできるけれど、Bという商品は大型なので1個しかカートインできない」など、
もっとスクリプトを書かないといけない可能性もあります!
//カートページの数量スピナーボタン(minus)
$('.spinner-down').on('click', function () {
let current_qty = parseInt($(this).nextAll('input').val());
let change_qty = 0;
if(current_qty < 1){
change_qty = 0;
}
else{
change_qty = current_qty - 1;
}
$(this).nextAll('input').attr("value", change_qty);
var item_index = $(this).attr("item_index");
lineitemQuantity( item_index, change_qty )
});
//カートページの数量スピナーボタン(plus)
$('.spinner-up').on('click', function () {
let current_qty = parseInt($(this).prevAll('input').val());
let change_qty = 0;
if(current_qty > 4){
change_qty = 5;
}
else{
change_qty = current_qty + 1;
}
$(this).prevAll('input').attr("value", change_qty);
var item_index = $(this).attr("item_index");
lineitemQuantity( item_index, change_qty )
});