前回の記事はこちら
ハイブリットモバイルアプリフレームワークのIonicを使って、架空のアパレルショップにおける注文アプリを作成する。
第6回目である今回は、カートアイコンにショッピングカート内の商品数を表示するバッジをつけるところまで
こちらのURLで、完成版のアプリを実際に操作することができます
https://l08084.github.io/ionic-sample-shopping-app/www
github.com
バージョン情報
Angular(JavaScriptのWebフレームワーク)ベースの、ハイブリットモバイルアプリ用フレームワークである「Ionic」を使っている
- ionic-angular@3.9.2
- Angular@5.2.10
- Google Chrome バージョン: 60.0.3112.113
タブバーにバッジを表示する
Ionicのタブには、インプットプロパティtabBadge
があるため、タブバーのアイコンにバッジを表示するだけなら、簡単にすみます。
src/pages/tabs/tab.html
:
<ion-tabs>
<ion-tab [root]="tab1Root" tabTitle="商品" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabTitle="カート" tabIcon="cart" tabBadge="4" tabBadgeStyle="danger"></ion-tab>
</ion-tabs>
上記のコードでは、カートアイコン上にバッジで「4」を表示しています
バッジ上の数値とカート内の商品数を同期させる
このままではバッチに固定の数値が表示されているだけで意味がないので、ショッピングカート内の商品数とバッジ上で表示されている数値が常に一致するようにしてあげる必要があります。
IonicのEventsを使う
カート内の商品数とバッジ上の数値を同期させる件ですが、IonicのEventsを使って実現します。Eventsはいわゆる出版-購読型モデルを実現するIonicのAPIになります。
今回は、商品をカートに入れるなど、カート内の商品数が更新されるタイミングでPublish(出版)を実施し、タブ側のコンポーネントではSubscribe(購読)を行うことによって、タブ側で常に最新のカート内の商品数を取得することができる...といった風に使います。
タブ側でSubscribeを行う
実際にコードを書いていきます。まずは、タブバーコンポーネントの方から。
src/pages/tabs/tab.ts
:
import { Component } from "@angular/core";
import { HomePage } from "../home/home";
import { CartPage } from "../cart/cart";
import { Events } from "ionic-angular";
@Component({
templateUrl: "tabs.html"
})
export class TabsPage {
public tab1Root = HomePage;
public tab2Root = CartPage;
public itemCount = 0;
constructor(public events: Events) {}
ionViewDidLoad() {
this.events.subscribe(
"cart:updated",
count => (this.itemCount = count ? count : 0)
);
}
}
上記のコードでは、タブバーコンポーネント初期作成時(ionViewDidLoad())に、トピック"cart:updated"
とアロー関数を引数に、Subscribe(購読)を行なっています。こうすることによって、同一トピック(つまり"cart:updated"
)のPublish(出版)が行われる度に、アロー関数が実行されるため、バッジの値itemCount
は常に最新の値になります。
ちなみにタブバーのテンプレートファイル
src/pages/tabs/tab.html
:
<ion-tabs>
<ion-tab [root]="tab1Root" tabTitle="商品" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabTitle="カート" tabIcon="cart" tabBadge="{{itemCount}}" tabBadgeStyle="danger"></ion-tab>
</ion-tabs>
カート内の商品数が変更されるタイミングでPublishを行う
あとは、ショッピングカート内の商品数が更新されるタイミングでPublish(出版)を行いさえすれば、カートアイコンのバッジ上に正しい商品数が表示される。
- カート内の商品数が更新されるタイミング
- アプリの初期表示時
- カートに商品を追加した時
- 注文を確定して、カートの中身が空になった時
アプリの初期表示時
前回起動時に、商品をカートに入れていた場合は、ストレージの機能により、カート内に商品が残ったままであるため、アプリ起動時には必ず商品数が0になる、というわけではない。
なので、アプリ起動時にも、ストレージの中身をチェックして、商品の数をPublishしてあげる必要がある。
タブ(src/pages/tabs/tab.ts
):
import { Component } from "@angular/core";
import { HomePage } from "../home/home";
import { CartPage } from "../cart/cart";
import { Events } from "ionic-angular";
import { Storage } from "@ionic/storage";
@Component({
templateUrl: "tabs.html"
})
export class TabsPage {
public tab1Root = HomePage;
public tab2Root = CartPage;
public itemCount = 0;
constructor(private events: Events, private storage: Storage) {}
ionViewDidLoad() {
this.events.subscribe(
"cart:updated",
count => (this.itemCount = count ? count : 0)
);
this.storage
.length()
.then(result => {
if (result !== 0) {
this.storage
.get("items")
.then(items => {
const count = items.length;
this.events.publish("cart:updated", count);
})
.catch(err => console.log(`storage error: ${err}`));
}
})
.catch(err => console.log(`storage error: ${err}`));
}
}
カートに商品を追加した時
ショッピングカートに商品を追加したタイミングでも、当然カート内の商品の数が変わるため、Publishしてあげる必要がある。
商品詳細画面(src/pages/detail/detail.ts
):
import { Component } from "@angular/core";
import { NavController, NavParams, Events } from "ionic-angular";
import { Storage } from "@ionic/storage";
import { Product } from "../../model/product.model";
@Component({
selector: "page-detail",
templateUrl: "detail.html"
})
export class DetailPage {
product: Product;
constructor(
private navCtrl: NavController,
private navParams: NavParams,
private storage: Storage,
private events: Events
) {}
ngOnInit() {
this.product = this.navParams.get("product");
}
@param{Product}
addItem(product: Product) {
let itemList = [];
this.storage
.length()
.then(result => {
if (result === 0) {
itemList = [];
itemList.push(product);
this.storage.set("items", itemList);
this.events.publish("cart:updated", 1);
} else {
this.storage
.get("items")
.then(items => {
items.push(product);
const count = items.length;
this.storage.set("items", items);
this.events.publish("cart:updated", count);
})
.catch(err => console.log(`storage error: ${err}`));
}
})
.catch(err => console.log(`storage error: ${err}`));
this.navCtrl.pop();
}
}
注文を確定して、カートの中身が空になった時
注文を確定して、未決済の商品(つまりカート内の商品)が0件になったときも、Publishして購読者に最新の商品数を送ってあげる必要がある。
カート画面(src/pages/cart/cart.ts
):
order() {
const confirm = this.alertCtrl.create({
title: "注文を確定しますか?",
buttons: [
{
text: "キャンセル",
handler: () => {}
},
{
text: "OK",
handler: () => {
let alert = this.alertCtrl.create({
title: "ご注文を受け付けました!",
subTitle: "ご指定の住所までのお届け時間は、20-30分程です",
buttons: ["OK"]
});
alert.present();
this.storage.clear();
this.productList = [];
this.isEmpty = true;
this.events.publish("cart:updated", 0);
}
}
]
});
confirm.present();
}
ここまで書くと、ショッピングカート内の商品数と、バッジの表示が同期されます。
次回の記事