LoginSignup
0

More than 1 year has passed since last update.

NCMBとFramework7を使った設定画面コンポーネントの紹介と使い方

Last updated at Posted at 2022-03-06

NCMBはモバイルアプリ開発におけるバックエンド機能(認証、データストア、ファイルストア、プッシュ通知など)を提供しています。バックエンドなのでAPIベースで利用するのが基本で、UI(アプリ側)は各自で開発する仕組みになっています。

現在、数多くのアプリが存在し、その中には定番とも言える機能があります。そうした定番機能を各フレームワークごとに実装しておくことで、再利用性高くNCMBが利用できるかと思います。

今回はFramework7で作った設定画面コンポーネントを紹介します。Monacaアプリでも利用可能です。

FireShot Capture 140 - 20220304131326 Auth - localhost.jpg

UIについて

コンポーネントは1つのHTMLだけで実装されているのが特徴です。そのため、基本的には以下の方法で導入・利用ができます。

  1. 必要なSDKの読み込み
  2. 必要なキーの取得
  3. NCMBの初期化
  4. 設定画面の設置

用意されている画面(機能)は次の通りです。

設定画面

設定画面では公開情報、非公開情報を設定できます。公開情報としてはたとえば表示名、プロフィール、プロフィール画像などを想定しています。

FireShot Capture 140 - 20220304131328 Auth - localhost.jpg

設定の仕様

  • 公開情報、非公開情報によって保存するクラスが異なります
  • プロフィール画像をアップロードできます
  • 利用できるのはテキスト、数字、ラジオボタンになります

必要なライブラリ・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 ファイルストアに保存(画像のみ)

入力内容はカスタマイズしてください。

FireShot Capture 140 - 20220304131326 Auth - localhost.jpg

まとめ

Profileクラスは誰でも読み込み可、関連したユーザーがだけが編集できる権限で保存されます。ユーザークラスは本人のみ読み書き可能です。メールアドレスなどの情報は公開されないので安全に利用できます。

認証が伴うアプリでは設定画面がはよく利用されるかと思います。イチから開発するのは面倒ですが、これを使うことで実装は簡単になります。ぜひ試してください。

mBaaSでサーバー開発不要! | ニフクラ mobile backend

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0