ShoppingCart 拡張アプリの推しポイントを紹介する記事
目次
これは a-blog cms Advent Calendar 2022 19日目の記事です。
今回は、現在開発中の ShoppingCart 拡張アプリについて、個人的にここは推しポイントだというところを紹介していきたいと思います。
ShoppingCart 拡張アプリとは
ShoppingCart 拡張アプリとは、a-blog cms で EC サイトを構築できるようにするための拡張アプリです。
a-blog cms に標準機能として搭載されているカート機能と何が違うの?という疑問が出てきそうですが、標準機能のカート機能とは主に以下の点で異なります。
- クレジットカード決済ができる
- 決済フォームが自由に構築できる
- サンプルテーマとして Square テーマがついてくる
現在開発中なので、まだユーザーの皆様に使っていただける状態にはなっていないのですが、ほぼほぼ完成に近づいてきたため今回紹介したいと思います。
また、基本的は使い方や機能については、正式リリース時やドキュメントなどで詳しく説明する予定ですので、今回のアドベントカレンダーの記事では個人的にこだわった推しポイントについて紹介したいと思います。
API機能 × Vue.js で実装された ショッピングカート機能
ShoppingCart 拡張アプリに同梱されている Square テーマでは、a-blog cms Ver. 3.0.0 から実装されたモジュールの GET API 機能を Vue.js と組み合わせてショッピングカート機能を実装しています。
JavaScript で実装しているため、ページ遷移をせずともショッピングカートへの商品の追加が反映されたり、カート内商品一覧ページで、数量の更新や削除を行った場合に、注文金額の部分がすぐに再計算されます。
また、今回再利用性やカスタマイズ性というところにもこだわりました。
例えば、square/src/js/shopping-cart というディレクトリにショッピングカート機能に関する JavaScript はすべてまとまっているため、弊社で開発している a-dispatcher というライブラリを併用して以下のように記述することで特定のブログでのみカート機能を利用することができます。
import domContentLoaded from 'dom-content-loaded';
import Dispatcher from 'a-dispatcher'; // a-dispather のインポート
/**
* Dispatcher
*/
const dispatcher = new Dispatcher();
// ダイナミックインポート
dispatcher.addRoute('^/shop/', async () => {
const { default: shoppingCart } = await import(
/* webpackChunkName: "shopping-cart" */ './shopping-cart'
);
domContentLoaded(() => {
shoppingCart(document);
});
});
dispatcher.run(window.location.pathname);
また、カスタマイズ性というところに関しては、JavaScript で Ajax を活用してサーバーと通信を行う場合は JavaScript 側でデータを組み立てて、データを送信する場合が多いかと思いますが、Square テーマでは FormData という Web API を活用して、form 要素のデータをそのまま送信するようにしています。
これにより、HTMLのテンプレート部分で Vue.js の独自記法で書く必要がある部分が最小限になるため、Vue.js に精通していない方でもある程度 HTML の編集がしやすくなりました。
HTMLベースでも実装できる ショッピングカート機能
先程、Square テーマではショッピングカート機能を JavaScript で実装しているという内容を書きましたが、あくまで Square テーマでは JavaScript で実装しているというだけであり、HTMLベースでもショッピングカート機能を実装することができるように作られています。
当初は、slim という PHPフレームワークを使って実装されていたため、レスポンスが JSON でしか返ってこず、JavaScript をつかってショッピングカート機能を実装する必要がありました。しかし、a-blog cms ユーザーは JavaScript が得意な方ばかりではないので、モジュールとして提供できるようにすることで、HTMLベースでもショッピングカート機能を実装できるようにしています。
例えば、以下はショッピングカートに商品(エントリー)を追加する機能を実装する機能の実装例です。
<form action="" method="post" enctype="multipart/form-data">
<div class="entry-price-bottom-box">
<table class="entry-item-select-table">
<!-- BEGIN_IF [{item_stock}/em/_or_/{item_stock}/gte/1] -->
<!-- 在庫管理が無効な場合 -->
<tr>
<th>個数</th>
<td>
<select name="quantity">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
<input type="hidden" name="cart[]" value="quantity">
</td>
</tr>
<!-- END_IF -->
</table>
</div>
<!-- BEGIN_IF [{item_stock}/em/_or_/{item_stock}/gte/1] -->
<!-- 在庫管理が無効な場合 or 在庫数が1以上の場合に表示 -->
<button class="btn is-width-full" type="submit" name="ACMS_POST_ShoppingCart_AddItem">
<span>カートに入れる</span>
</button>
<!-- ELSE -->
<!-- 在庫管理が有効かつ在庫数が1未満(つまり在庫切れ)の場合に表示 -->
<button class="btn is-width-full" type="button">
<span>この商品は売り切れました</span>
</button>
<!-- END_IF -->
<input type="hidden" name="eid" value="%{EID}">
<input type="hidden" name="cart[]" value="eid">
</form>
ShoppingCart 拡張アプリでは、ショッピングカートに商品(エントリー)を追加するための POST モジュールとして、 ShoppingCart_AddItem というモジュールを提供しているため、こちらのモジュールを実行するためのフォームのテンプレートを記述します。
POSTモジュールとして提供しているため、a-blog cms の フォームを構築するような感じで、ショッピングカートに商品(エントリー)を追加する機能が実装できるようになっています。
1点注意点としては、ショッピングカート機能で必要なフィールドを送信する場合は 、name 属性に cart[]
を、 value 属性に 送信したいフィールド(項目)名を指定した input タグを一緒に記述する必要があるところです。通常のフォームだと field[]
というカスタムフィールドの形式でフォームのフィールドを追加していくため注意が必要です。
そして、POST モジュールで処理をするということは、処理が成功したかどうかというデータを表示できるようにする必要があります。在庫以上の商品を追加しようとしたりして、商品をカートに追加できなかった場合などにエラーメッセージがないとユーザーがなぜ商品をカートに追加できなかったのか迷わせてしまうというのは避けたいところです。
ShoppingCart 拡張アプリでは、ショッピングカートに商品を追加したり、ショッピングカートから商品を削除したりなど、ショッピングカートの操作に関する処理の結果を表示するための GET モジュールとして、ShoppingCart モジュールを用意しています。
以下はショッピングカートに商品(エントリー)を追加するボタンを押して、ShoppingCart_AddItem を実行後の結果を表示するテンプレートの実装例です。
<!-- BEGIN_MODULE ShoppingCart -->
<!-- BEGIN add -->
<!-- BEGIN_IF [{status}/eq/success] -->
<p class="acms-alert acms-alert-info">「%{ENTRY_TITLE}」をカートに追加しました。</p>
<!-- ELSE -->
<p class="acms-alert acms-alert-danger validator-result-{eid:validator#required}">カートに商品を追加できませんでした。</p>
<p class="acms-alert acms-alert-danger validator-result-{quantity:validator#required}">数量を選択してください。</p>
<p class="acms-alert acms-alert-danger validator-result-{quantity:validator#regex}">数量の形式が間違っています。</p>
<p class="acms-alert acms-alert-danger validator-result-{quantity:validator#min}">数量の形式が間違っています。</p>
<p class="acms-alert acms-alert-danger validator-result-{quantity:validator#stock}">注文可能な数量を超えています。</p>
<!-- END_IF -->
<!-- END add -->
<!-- END_MODULE ShoppingCart -->
{status}
という変数でショッピングカートへ商品(エントリー)を追加する処理が成功したかどうかを判定できるため、IFブロックで分岐して、成功している場合は、成功メッセージ、失敗した場合はエラーメッセージを表示します。
上記のように、ShoppingCart 拡張アプリの ショッピングカート機能は JavaScript があまり得意ではない方でも a-blog cms のカスタマイズができる方であれば HTML ベースでも実装できるようになっております。
アクセシビリティを考慮したモーダルコンポーネント
モーダルコンポーネントのアクセシビリティ対応は以外にもめんどくさいものです。少し Google で検索しただけでも以下のような要件がでてきます。
- モーダル要素に role 属性、aria-modal 属性、aria-labelledby 属性、aria-describedby 属性が付与されている
- モーダルを開くと、モーダル内の最初のフォーカス可能な要素に自動でフォーカスされる
- モーダルが開いている間、モーダル以外の要素に aria-hidden 属性が付与される
- モーダルが開いている間、モーダル以外の要素のスクロールが無効化される
- モーダルが開いている間、モーダル内でフォーカスがトラップされる
- Esc キーを押下すると、モーダルが閉じる
- モーダルの外側をクリックすると、モーダルが閉じる
- モーダルを閉じると、モーダルが開く前にフォーカスされていた要素にフォーカスが戻る
HTML だけで実装できる内容もありますが、多くは JavaScript を使って実装する必要があります。
Square テーマでは、ショッピングカートに商品(エントリー)を追加した場合にモーダルコンポーネントが表示されるようになっていますが、このモーダルコンポーネントは上記のアクセシビリティ対応を(ほぼ)クリアするように実装しています。
実際に ShoppingCart 拡張アプリと Square テーマの動作を体験できる、 appleple.shop で適当な商品(水がおすすめ)をカートに追加していただくとモーダルコンポーネントが表示されますので、「モーダルを開くと、モーダル内の最初のフォーカス可能な要素に自動でフォーカスされる」や、「モーダルが開いている間、モーダル内でフォーカスがトラップされる」、「モーダルが開いている間、モーダル以外の要素のスクロールが無効化される」といったところがきちんと達成できていることを確認できるかと思います。
このように、Square テーマでは普段見落とされがちなアクセシビリティの部分にもできるだけ配慮できるように作られています。
まとめ
今回は、開発中の ShoppingCart 拡張アプリについて開発者目線での推しポイントについて紹介させていただきました。
来年は、ShoppingCart 拡張アプリを正式リリースできるように頑張りたいと思います。また、ShoppingCart 拡張アプリはまだまだ発展途上な部分もあるかと思いますので皆様からのご意見をもとによりパワーアップしていきますのでよろしくお願いいたします。
明日の a-blog cms Advent Calendar 2022 20日目は坂本邦夫さんです!