NCMBはモバイルアプリ開発におけるバックエンド機能(認証、データストア、ファイルストア、プッシュ通知など)を提供しています。バックエンドなのでAPIベースで利用するのが基本で、UI(アプリ側)は各自で開発する仕組みになっています。
現在、数多くのアプリが存在し、その中には定番とも言える機能があります。そうした定番機能を各フレームワークごとに実装しておくことで、再利用性高くNCMBが利用できるかと思います。
今回はFramework7で作った設定画面コンポーネントを紹介します。Monacaアプリでも利用可能です。
UIについて
コンポーネントは1つのHTMLだけで実装されているのが特徴です。そのため、基本的には以下の方法で導入・利用ができます。
- 必要なSDKの読み込み
- 必要なキーの取得
- NCMBの初期化
- 設定画面の設置
用意されている画面(機能)は次の通りです。
設定画面
設定画面では公開情報、非公開情報を設定できます。公開情報としてはたとえば表示名、プロフィール、プロフィール画像などを想定しています。
設定の仕様
- 公開情報、非公開情報によって保存するクラスが異なります
- プロフィール画像をアップロードできます
- 利用できるのはテキスト、数字、ラジオボタンになります
必要なライブラリ・SDKの読み込み
今回利用しているライブラリ・SDKは次の通りです。
- NCMB JavaScript SDK
これらを www/index.html
で読み込みます。
<script src="js/ncmb.min.js"></script>
必要なキー・トークンの取得
NCMBのアプリケーションキーとクライアントキーを取得します。
NCMBの初期化
www/js/app.js
にてNCMBを初期化します。今回は www/js/config.json
というファイルにキーを記述しているので、以下のように読み込みを行っています。
const $ = Dom7;
(async () => {
const device = Framework7.getDevice();
// 設定ファイルの読み込み
const config = await (await fetch('./js/config.json')).json();
// NCMBの初期化
window.ncmb = new NCMB(config.applicationKey, config.clientKey);
// Framework7の初期化
window.app = new Framework7({
name: 'NCMB Setting',
theme: 'auto',
el: '#app',
id: 'com.nifcloud.mbaas.map',
store: store,
routes: routes,
input: {
scrollIntoViewOnFocus: device.cordova && !device.electron,
scrollIntoViewCentered: device.cordova && !device.electron,
},
statusbar: {
iosOverlaysWebView: true,
androidOverlaysWebView: false,
},
on: {
init: function () {
if (this.device.cordova) {
cordovaApp.init(this);
}
},
},
});
})();
ルーティングの設定
設定画面はログインしていないと表示されない画面になります。Framework7でNCMBの認証状態によってルーティングを振り分ける - Qiitaにて紹介した方法を使ってルーティングの設定を行います。ログイン、会員登録画面は認証コンポーネントを使っています。
const beforeEnter = async ({resolve, reject, router}) => {
// 現在ログインしているユーザー情報を取得
const currentUser = ncmb.User.getCurrentUser();
// 認証していない場合はnullになる
if (!currentUser) {
// rejectを実行
reject();
// 認証画面に遷移
router.navigate('/auth');
// 処理完了
return;
}
try {
// データストアにダミーアクセス
await ncmb.DataStore('Hello').fetch();
// アクセスできればresolveを実行( /settingsを表示)
resolve();
} catch (e) {
// 駄目だった場合は認証情報を削除
localStorage.removeItem("NCMB/"+ncmb.apikey+"/currentUser");
// rejectを実行
reject();
// 認証画面に遷移
router.navigate('/auth');
}
};
const routes = [
{
path: '/',
url: './index.html',
},
{
path: '/auth',
componentUrl: './pages/auth.html',
},
{
path: '/settings',
componentUrl: './pages/settings.html',
beforeEnter,
},
{
path: '(.*)',
url: './pages/404.html',
},
];
そして、今回は www/index.html
にて設定画面を表示するリンクを追加しています。
<div id="app">
<div class="view view-init safe-areas">
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">設定</div>
</div>
</div>
<div class="page-content" style="margin-top: 2em; text-align: center;">
<a href="/settings"><i class="f7-icons">gear_alt_fill</i></a>
</div>
</div>
</div>
</div>
設定画面の追加
settings.htmlをダウンロードして、 www/pages/settings.html
として配置します。
設定画面のカスタマイズ
設定画面のHTMLは次のようになっています。
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">設定</div>
</div>
</div>
<div class="page-content">
<form class="profile">
<div class="block-title">公開情報</div>
<div class="list">
<ul>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label"></div>
<div class="item-input-wrap">
<input type="text" name="displayName" placeholder="ユーザー名" value="${profile.displayName}" data-public="1" />
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label"></div>
<div class="item-input-wrap">
<textarea class="resizable" name="profile" data-public="1">${profile.profile}</textarea>
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">写真</div>
<div class="item-input-wrap">
${ image ?
$h`<img class="profileImage" src=${image} @click=${openFilePicker} />`
:
$h`<i class="f7-icons size-150" @click=${openFilePicker}>person_alt_circle</i>`
}
<span style="display: none;">
<input type="file" name="photo" data-public="1" accept="image/*" @change=${selectPhoto} />
</span>
</div>
</div>
</li>
</ul>
<div class="block-title">非公開情報</div>
<ul>
<li class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">誕生日</div>
<div class="item-input-wrap">
<input type="date" name="birthDate" placeholder="2013-09-01" value="${currentUser.birthDate}" />
</div>
</div>
</li>
<li>
<div class="block-title">メールマガジン受信</div>
<label class="item-radio item-radio-icon-start item-content">
${currentUser.mailMagagine ?
$h`<input type="radio" name="mailMagagine" value="true" checked="checked" />`
:
$h`<input type="radio" name="mailMagagine" value="true" />`
}
<i class="icon icon-radio"></i>
<div class="item-inner">
<div class="item-title">する</div>
</div>
</label>
<label class="item-radio item-radio-icon-start item-content">
${currentUser.mailMagagine ?
$h`<input type="radio" name="mailMagagine" value="false" />`
:
$h`<input type="radio" name="mailMagagine" value="false" checked="checked" />`
}
<i class="icon icon-radio"></i>
<div class="item-inner">
<div class="item-title">しない</div>
</div>
</label>
</li>
<li>
<a href="#" class="button button-large" @click=${save}>保存する</a>
</li>
</ul>
</div>
</form>
</div>
</div>
</template>
設定は次のようになります。
要素 | 内容 |
---|---|
data-public | "1" を設定するとProfileクラス(公開情報)、ない場合はUserクラス(非公開情報)として保存されます |
name | データストアのフィールド名 |
利用できる入力形式は以下になります。
タイプ | NCMBの型 |
---|---|
text | テキスト型 |
number | 数値型 |
date | 日付型 |
textarea | テキスト型 |
radio | 真偽値型 |
file | ファイルストアに保存(画像のみ) |
入力内容はカスタマイズしてください。
まとめ
Profileクラスは誰でも読み込み可、関連したユーザーがだけが編集できる権限で保存されます。ユーザークラスは本人のみ読み書き可能です。メールアドレスなどの情報は公開されないので安全に利用できます。
認証が伴うアプリでは設定画面がはよく利用されるかと思います。イチから開発するのは面倒ですが、これを使うことで実装は簡単になります。ぜひ試してください。