FJCT_ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

Monaca + NCMBでタスク管理アプリを作る【その3:タスク登録/編集機能を作る】

f:id:mbaasdevrel:20201119154758p:plain

MonacaとNCMBで簡単なアプリを作ってみるハンズオンの資料です。今回のテーマはタスク管理アプリです。この記事ではタスクの登録および一覧、編集機能を実装します。なおコードはNCMBMania/task_appにて公開しています。

タスクを登録する

f:id:mbaasdevrel:20201119181050p:plain

タスクの登録処理は add.html#addTask をクリックした際のイベントで作成します。

$('#addTask').on('click', async e => {
  // 変数を準備する
  const title = $('#title').val();
  const date = $('#date').val();
  const body = $('#body').val();
  try {
    // NCMBにタスクを登録する
    await addTask(title, date, body);
    $('#nav')[0].popPage();
  } catch (e) {
    ons.notification.alert('タスクの作成に失敗しました');
  }
})

この時のaddTaskは次のようになります。ACLはタスクを登録したユーザ自身だけに読み込み、書き込み権限を付与しています。

// タスクを追加する処理です
async function addTask(title, date, body) {
  // タスクのインスタンスを作成します
  const task = new (ncmb.DataStore('Task'));
  // 入力した情報をセットします
  task
    .set('title', title)
    .set('date', new Date(date))  // 日付型にします
    .set('done', false)           // デフォルトは未完了です
    .set('body', body);
  // ACLを作成します
  const user = ncmb.User.getCurrentUser();
  const acl = new ncmb.Acl();
  acl
    .setUserReadAccess(user, true)   // ユーザ自身のみ読み込み可
    .setUserWriteAccess(user, true); // ユーザ自身のみ書き込み可
  // ACLを設定して保存
  await task
    .set('acl', acl)
    .save();
}

一覧画面を作る

一覧画面では、画面を表示したタイミングでタスクを読み込んで表示します。

ons.getScriptPage().onShow = async function() {
  await getTaskList();
  renderTasks();
}

この時の getTaskList は次のようになります。

let tasks = [];
async function getTaskList() {
  // タスクのクラスを作成
  const Task = ncmb.DataStore('Task');
  // 未了なタスクを一覧で取得
  tasks = await Task
    .equalTo('done', false)
    .limit(100)
    .order('date') // 並び順は日付ごと
    .fetchAll();
}

タスク一覧を取得したら、後はこれを一覧表示するだけです。

function renderTasks() {
  const html = [];
  let date = null;
  for (const task of tasks) {
    const taskDate = task.get('date').iso;
    if (date !== taskDate) {
      html.push(`<ons-list-header>${dayjs(taskDate).format('YYYY年MM月DD日')}</ons-list-header>`);
      date = taskDate;
    }
    html.push(`
      <ons-list-item swipeable expandable data-objectid="${task.get('objectId')}">
        <div class="left">
          <ons-icon icon="fa-check" class="done"></ons-icon>&nbsp;&nbsp; 
          <ons-icon icon="fa-edit" class="edit"></ons-icon>
        </div>
        ${task.get('title')}
        <div class="expandable-content">
          ${task.get('body').replace(/\n/, '<br />')}
        </div>
      </ons-list-item>
    `);
  }
  $('#tasks').html(html.join(''));
}

f:id:mbaasdevrel:20201119181120p:plain

タスクを完了する

タスク一覧でチェックアイコンをタップするとタスクを完了状態にします。これは .done をタップした際のイベントを使います。

// タスクを完了させる
$(document).on('click', '.done', async e => {
  // タップした対象のobjectIdを取得
  const objectId = $(e.target).parents('ons-list-item').data('objectid');
  // タスクオブジェクトを取得する
  const task = getTask(objectId);
  // タスクのステータスを更新する
  await task.set('done', true).update();
  // タスクを一覧データから消す
  tasks = tasks.filter(t => t.get('objectId') !== objectId)
  // 再描画
  renderTasks();
});

function getTask(objectId) {
  return tasks.filter(t => t.get('objectId') === objectId)[0];
}

タスクの編集画面に遷移する

タスク一覧で編集アイコンをタップするとタスクの編集画面に遷移します。これは .edit をタップした際のイベントを使います。ここで行っているのはタスクを完了にする処理と同じようにタスクを取得し、それをedit.htmlに送っているだけです。

$(document).on('click', '.edit', async e => {
  const objectId = $(e.target).parents('ons-list-item').data('objectid');
  const task = getTask(objectId);
  $('#nav')[0].pushPage('edit.html', {data: {task}})
});

タスク編集画面を作る

タスク編集画面は edit.html になります。ここでは前画面から送られてきたタスクデータを表示します。taskはapp.jsで定義した変数になります。

ons.getScriptPage().onShow = async function() {
  task = this.data.task;
  for (const key in task) {
    let value = task.get(key);
    if (key === 'date') {
      value = dayjs(task.get(key).iso).format('YYYY-MM-DD');
    }
    $(`.task_${key}_label`).html(value);
    $(`.task_${key}`).val(value);
  }
}

タスクの更新は #updateTask をタップした際のイベントで実行します。

// タスクを更新する
$('#updateTask').on('click', async e => {
  const title = $('#title').val();
  const date = $('#date').val();
  const body = $('#body').val();
  try {
    await updateTask(title, date, body);
    $('#nav')[0].popPage();
  } catch (e) {
    ons.notification.alert('タスクの更新に失敗しました');
  }
})

updateTask は次のようになります。新規作成時の処理と変わりません。違うのは save ではなく、updateになっていることです。

async function updateTask(title, date, body) {
  task
    .set('title', title)
    .set('date', new Date(date))
    .set('body', body);
  await task.update();
}

f:id:mbaasdevrel:20201119181145p:plain

まとめ

これでタスク管理アプリの完成です。mBaaSと組み合わせることで認証を使ったり、データを登録/更新するのが簡単にできます。

今回のハンズオンで利用したmBaaSの機能は次の通りです。

  • 会員登録(ID/パスワード)
  • 会員認証(ID/パスワード)
  • データストア登録/更新
  • データストア検索

mBaaSには他にもたくさんの機能があります。ぜひほかのハンズオンで体験してください。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。