NCMBとMonacaを使ってカレンダーアプリを作ります。予定を登録したり、Framework7のカレンダーコンポーネントを使って予定を表示できるというアプリです。
まず最初の記事では画面の説明とSDKの導入までを進めます。
コードについて
今回のコードはNCMBMania/monaca-calendar-appにアップロードしてあります。実装時の参考にしてください。
利用技術について
今回は次のような組み合わせになっています。
- Monaca
- Framework7
- moment.js(Dateオブジェクト操作用)
- NCMB JavaScript SDK
仕様について
今回はID/パスワード認証を利用しています。カレンダー表示についてはFramework7のCalendar / Datepicker | Framework7 Documentationを利用しています。また、Framework7はVanilla JSで、VueやReactなどのUIフレームワークは利用していません。
利用する機能について
カレンダーアプリで利用するNCMBの機能は次の通りです。
- 会員管理
- ID/パスワード認証
- データストア
- 予定の登録・更新・削除
- 予定の検索
画面について
今回は以下の3つの画面があります。
www/pages/login.html
ログイン画面です。ID/パスワードを使って認証します。今回はユーザー登録とログイン画面を兼ねています。
<div class="block-title">ユーザーIDとパスワードを入力してください</div>
<form id="login">
<div class="list no-hairlines-md">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">ユーザーID</div>
<div class="item-input-wrap">
<input type="text" name="userName" placeholder="お名前" value="goofmint" required/>
</div>
</div>
</div>
</li>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">パスワード</div>
<div class="item-input-wrap">
<input type="password" name="password" placeholder="パスワード" value="goofmint" required/>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block block-strong">
<p class="row">
<a href="#" @click=${login} class="col button">ログイン or ユーザー登録</a>
</p>
</div>
</form>
www/pages/calendar.html
カレンダー画面です。NCMBのデータストアから予定を取得して、画面にドット表示で反映させます。日付を選択すると、該当日の予定を一覧表示します。
<div id="calendar"></div>
<div class="block-title">
${ selectedDate.value ? moment(selectedDate.value).format('YYYY年MM月DD日') : "日付を選択してください"}
</div>
<div class="list media-list chevron-center">
${ selectedDate.value === null || schedules.value.length === 0 ?
$h`<div class="block">予定はありません</div>` :
$h`<ul>
${ schedules.value
.filter(schedule => moment(schedule.startDate.iso).format('YYYY-MM-DD') === moment(selectedDate.value).format('YYYY-MM-DD'))
.map(schedule => $h`
<li>
<a href="/form/${schedule.objectId}/" class="item-link item-content">
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">${schedule.title}</div>
<div class="item-after">
${moment(schedule.startDate.iso).format('HH:mm')}〜${moment(schedule.endDate.iso).format('HH:mm')}
</div>
</div>
<div class="item-text">
${schedule.body}
</div>
</div>
</a>
</li>
`)}
</ul>`
}
</div>
www/pages/form.html
予定を登録・更新または削除する画面です。日時の入力はFramework7のカレンダーコンポーネントを利用しています。
<div class="list no-hairlines-md">
<form id="schedule">
<ul>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" id="startDate" name="startDate" @change=${setEndDate} placeholder="日時" value="${targetDate}" />
<span class="input-clear-button"></span>
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" id="endDate" name="endDate" placeholder="終了日時" />
<span class="input-clear-button"></span>
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" name="title" placeholder="タイトル" value="${schedule.title}" />
<span class="input-clear-button"></span>
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<textarea class="resizable" name="body">${schedule.body}</textarea>
<span class="input-clear-button"></span>
</div>
</div>
</li>
</ul>
<div class="block block-strong">
<p class="row">
<a href="#" @click=${saveSchedule} class="col button">保存</a>
</p>
${ schedule.objectId ?
$h`<p class="row">
<a href="#" @click=${deleteSchedule} class="col button">削除</a>
</p>`
: ''
}
</div>
</form>
</div>
SDKのインストール
今回はMonacaのJS/CSSコンポーネントの追加と削除より、NCMBを追加します。アプリのテンプレートはFramework7のJavaScript版(VueやReactではなく)を選択しています。
NCMBのAPIキーを取得
mBaaSでサーバー開発不要! | ニフクラ mobile backendにてアプリを作成し、アプリケーションキーとクライアントキーを作成します。
js/config.jsonの作成
js/config.jsonを作成し、その中に先ほど取得したNCMBのAPIキーを設定します。内容は次のようになります。
{
"applicationKey": "YOUR_APPLICATION_KEY",
"clientKey": "YOUR_CLIENT_KEY"
}
初期化
初期化は js/app.js
にて行います。config.jsonを読み込む関係上、非同期処理内にて行います。cordovaの有無(アプリまたはプレビューの違いを検知)によって初期化時のイベント処理を変えています。
// NCMBの初期化用
const event = window.cordova ? 'deviceready' : 'DOMContentLoaded';
document.addEventListener(event, async (e) => {
// この中に処理を書きます
});
config.jsonの内容を読み込んで、NCMBとFramework7の初期化を行います。
window.config = await (await fetch('./js/config.json')).json();
window.ncmb = new NCMB(config.applicationKey, config.clientKey);
window.app = new Framework7({
name: 'My App', // App name
theme: 'auto', // Automatic theme detection
el: '#app', // App root element
// App store
store: store,
// App routes
routes: routes,
});
これでNCMBの初期化が完了します。
ルーティング設定
今回はチャット画面、ログイン画面の2つがあります。これを js/routes.js
に定義します。
const routes = [
{
path: '/',
url: './index.html',
},
// カレンダー画面
{
path: '/home/',
componentUrl: './pages/calendar.html',
beforeEnter,
},
// ログイン画面
{
path: '/login/',
componentUrl: './pages/login.html',
},
// 予定追加・更新画面
{
path: '/form/:id/',
componentUrl: './pages/form.html',
},
// Default route (404 page). MUST BE THE LAST
{
path: '(.*)',
url: './pages/404.html',
},
];
認証していない場合の判定処理
上記のルーティングで beforeEnter
を指定しています。ここで、カレンダー画面を表示する前に、認証状態を確認します。そしてログインしていない場合には、ログイン画面に遷移します。
// routes.jsに記述
const beforeEnter = async ({resolve, reject, router}) => {
// 現在ログインしているユーザー情報を取得
const currentUser = ncmb.User.getCurrentUser();
// 認証していない場合はnullになる
if (!currentUser) {
// rejectを実行
reject();
// 認証画面に遷移
router.navigate('/login/');
// 処理完了
return;
}
try {
// データストアにダミーアクセス
await ncmb.DataStore('Hello').fetch();
// アクセスできればresolveを実行(元々指定されている画面を表示)
resolve();
} catch (e) {
// 駄目だった場合は認証情報を削除
localStorage.removeItem("NCMB/"+ncmb.apikey+"/currentUser");
// rejectを実行
reject();
// 認証画面に遷移
router.navigate('/login/');
}
};
まとめ
今回はカレンダーアプリの仕様と画面、NCMBの初期化までを解説しました。次はログイン処理を実装します。