前回の記事はこちら
ハイブリットモバイルアプリフレームワークのIonicを使って、架空のアパレルショップにおける注文アプリを作成する。
第7回目である今回は、同じ商品を二つ買った場合でも、まとめて表示されない問題について解決します。
- デモ
こちらのURLで、完成版のアプリを実際に操作することができます
https://l08084.github.io/ionic-sample-shopping-app/www
- GitHubリポジトリ
バージョン情報
Angular(JavaScriptのWebフレームワーク)ベースの、ハイブリットモバイルアプリ用フレームワークである「Ionic」を使っている
- ionic-angular@3.9.2
- Angular@5.2.10
- Google Chrome バージョン: 60.0.3112.113
解決したい問題
現在のアプリ(AS IS)だと、同一の商品を3個購入した場合は、そのままレジ画面に3列分表示されてしまうという問題があります。それを、同一の商品を複数件購入した場合は、1列でまとめて表示するように、コードを改修します。
実装
複数個の商品オブジェクトをまとめて一つにする、groupBy
メソッドを以前の回で作ったサービスクラスProductProvider
に追加します。
src/providers/product/product.ts
:
// ...長いので省略 /** * 同一の商品(idが同じ)を一つのオブジェクトにまとめる * * @param {Product[]} productList カート内の商品リスト * @returns {Product[]} (同一の商品ついては、一つにまとめた状態の)カート内の商品リスト * @memberof ProductProvider */ groupBy(productList: Product[]): Product[] { const group = productList.reduce((result: Product[], current: Product) => { const element = result.find(p => p.id === current.id); if (element) { // 同一の商品がある場合 // 商品の数量をインクリメントする element.quantity += 1; } else { result.push(current); } return result; }, []); return group; } }
上記のgroupBy
メソッドをカート画面の初期表示時に呼び出す
src/pages/cart/cart.ts
:
// add this! // 同一の商品(idが同じ)を一つのオブジェクトにまとめる this.productList = this.productProvider.groupBy(result);
商品が複数個になった場合の価格の表示については、カート画面のテンプレートファイル側で「商品の1個あたりの値段 * 数量」の計算をすることで対応している(あまりテンプレート側で計算とかをするのはよくないと思うので、今後改善していきたい....)
src/pages/cart/cart.html
:
<div class="price">¥{{product.price * product.quantity}}</div>
ここまで書くと最初の図のTO BEのイメージ通り、同じ商品を複数購入した場合は、まとまって表示されるはずである。
余談
今回のような、”あるプロパティが同じ複数のオブジェクトをまとめて一つにする処理”は、自分にとっては鬼門で、本件と同様の問題が発生した時にまずいコードを書いてしまったことがある(以前書いたまずいコードについては、こちら)。
今回は、下記のサイトを参考にメソッドを書いた。(「SQLのgroup byのように集計する」という的確な表現だったり、説明がわかりやすい記事でとても参考にさせていただいた)
参考サイト
JavaScript オブジェクト配列をsqlのgroup byのように集計する