この記事では、kintone(キントーン)をデータベースとして利用したモバイルアプリを作成していきます。

キントーンにてサンプルアプリの一つとして提供されている「院内掲示板アプリ」をベースとしてiOS/Androidの掲示板アプリを作ります。

前回記事では、下の機能を実装していきました。

  1. アプリへのログイン機能
  2. スレッド一覧画面
  3. スレッド一覧の取得
  4. 新規スレッドの登録


今回の後編記事では、次の機能を作成していきます。

  1. スレッド詳細画面の作成
  2. スレッドのコメントの取得
  3. スレッドの添付ファイルの取得
  4. スレッドのコメントの登録

プロジェクトのソースコードは、GitHubに配置しています。
https://github.com/monaca-samples/kintone-bbs

スレッド一覧からの画面遷移

スレッド一覧画面でスレッドをタップしたら、スレッド詳細画面に遷移します。
これは www/pages/threads.html に定義しています。

// スレッド一覧をタップした際のイベント
const click = (record) => {
    // スレッド詳細画面に遷移
    $f7router.navigate(/threads/${record.$id.value}, {
        props: {
            record,
        },
    });
}

スレッド詳細画面

掲示板のスレッド詳細画面

スレッド詳細画面では、前の画面から送られてきたスレッドの詳細を表示します。

また、そのスレッドに投稿されたコメントを表示します。

ファイル www/pages/thread.html に、次のようにコーディングしています。

<div class="page-content">
    <div class="list media-list">
        <ul>
            <li>
                <div class="item-content">
                    <div class="item-inner">
                        <div class="item-title-row">
                            <div class="item-title">${record.title.value}</div>
                            <div class="item-after">${record.pubDate.value}</div>
                        </div>
                        <div class="item-subtitle">${record.level.value}</div>
                        <div class="item-text">${showText(record.body.value)}</div>
                    </div>
                </div>
            </li>
            <li>
                ${attachments.map(a => $h`
                    <div class="item-content">
                        <div class="item-inner">
                            <img src="${a}" width="100%" /> 
                        </div>
                    </div>
                `)}
            </li>
        </ul>
    </div>
    <div class="block-title">コメント</div>
    <div class="list media-list">
        <ul>
            ${comments.map(c => $h`
                <li>
                    <div class="item-content">
                        <div class="item-inner">
                            <div class="item-title-row">
                                <div class="item-title">${c.creator.name}</div>
                                <div class="item-after">${dayjs(c.createdAt).format('MM月DD日 HH:mm')}</div>
                            </div>
                            <div class="item-text">${c.text}</div>
                        </div>
                    </div>
                </li>   
            `)}

        </ul>
    </div>
    <div class="list inset">
        <ul>
            <li class="item-content item-input">
                <div class="item-inner">
                    <div class="item-input-wrap">
                        <textarea id="text" class="resizable"></textarea><br />
                        <button class="button" @click=${addComment}>コメントする</button>
                    </div>
                </div>
            </li>
        </ul>
    </div>
</div>

コメントの取得

続いてコメントの取得処理です。

コメントの取得は、スレッド詳細画面を表示したタイミングで、kinotoneへアクセスし取得しています。

下のコードの「initView( )」にて「getCommnets( )」を実行し、コメント取得しています。

// ファイル: www/pages/thread.html
export default (props, { $f7, $f7router, $update, $onMounted }) => {
    const { record } = props; // 前の画面から送られてくるスレッドデータ
    let comments = []; // コメント一覧用
    let attachments = []; // 添付ファイル用

    // 画面をマウントした際に実行されるイベント
    $onMounted(async () => {
        initView(); // 初期表示用
        getAttachments(); // 添付ファイルの取得
    });

    // 初期表示用関数
    const initView = async () => {
        // コメントの取得
        const res = await getComments({
      app: KINTONE_APP_ID,
            record: record.$id.value,
        });
        // コメントを変数に入れる
        comments = res.data.comments;
        // 画面更新
        $update();
    };
}

getComments 関数は、ファイル js/app.js にあります。

この関数では、kintoneのレコードコメント一括取得APIである次のURLにGETメソッドで
アクセスしています。

https://(サブドメイン名).cybozu.com/k/v1/record/comments.json

// ファイル: www/js/app.js
// コメント取得用関数
const getComments = (params) => {
  const options = {
    method: 'get',
    params,
  };
  return sendRequest(/record/comments.json, options);
}

添付ファイルの取得

掲示板へ添付ファイルを登録

次は、添付ファイルを取得する処理についてです。

getAttachments 関数でファイルの取得をしています。

(このアプリ扱う添付ファイルは、画像としています。)

// 添付ファイルの取得
const getAttachments = async () => {
    if (record.attachment.value.length === 0) return;
    try {
        // 添付ファイルのダウンロード
        const promises = record.attachment.value.map(a => downloadFile(a.fileKey));
        const response = await Promise.all(promises);
        attachments = response.map(res => URL.createObjectURL(res.data));
        $update();
    } catch (e) {
        console.log(e);
    }
}

downloadFile 関数は、 js/app.js にて定義されています。
次のkintoneのファイルダウンロードAPIを呼び出して実装しています。

https://(サブドメイン名).cybozu.com/k/v1/file.json

// ファイル: www/js/app.js
// ファイルダウンロード用
const downloadFile = (fileKey) => {
  const options = {
    method: 'get',
    params: {
      fileKey
    }
  };
  return sendRequest('/file.json', options, 'json', 'blob');
}

ダウンロードした内容は Blob 型になっています。

HTMLでBlob形式の画像を表示するため、
URL.createObjectURL を使って blob:〜 形式に変換しています。

また、このファイルを表示する際には index.html のCSP設定を、次のように変更する必要があり、少し注意が必要です。

<!-- 最後に blob: を追加します-->
<meta http-equiv="Content-Security-Policy" content="default-src * "self" "unsafe-inline" "unsafe-eval" data: gap: content: blob:">

ファイルの表示は、テンプレートの attachments にて処理しています。

//ファイル: www/pages/thread.html
<li>
    ${attachments.map(a => $h`
        <div class="item-content">
            <div class="item-inner">
                <img src="${a}" width="100%" /> 
            </div>
        </div>
    `)}
</li>

コメントの登録

コメントの登録画面

新しいコメントを入力しコメントボタンが押されたら、 addComment 関数が呼ばれます。

この関数では、kintoneへコメントを登録します。

また、コメントの登録後に、
いま登録したコメントを含めて、全体のコメントの再取得を行うために initView 関数を呼び出します。

   // ファイル: www/pages/thread.html
   // コメントを登録するイベント
    const addComment = async () => {
        // 入力値の取得
        const text = $("#text").val();
        // コメント投稿
        await postComment({
      app: KINTONE_APP_ID,
            record: record.$id.value,
            comment: {
                text,
            }
        });
        // 画面を表示し直し
        initView();
    };

postComment 関数は、 js/app.js にあります。
kintoneのレコードコメント投稿APIを利用しています。

POSTメソッドで、次のURLにアクセスしています。

https://(サブドメイン名).cybozu.com/k/v1/record/comment.json

// ファイル: www/js/app.js
// コメント登録用関数
const postComment = (data) => {
  const options = {
    method: 'post',
    data,
  };
  return sendRequest(/record/comment.json, options);
};

登録したコメントは、kintoneでも確認できます。

まとめ

今回のサンプルアプリでは、ファイル www/js/app.js に、kintoneへアクセスする共通処理をまとめています。

この共通処理を再利用することにより、Monaca上でkintone連携アプリを開発することもスムーズにできるかと思います。

JavaScriptとHTMLを利用して、カスタマイズしたkintoneモバイルアプリを開発することが可能ですので、ぜひMonacaをお試しいただければと思います。