JavaScriptカスタマイズを行うことによってkintoneの標準機能ではできないことを実現することができます。しかし、初心者の方にとっては少しハードルが高いですよね。複数のアプリが関わってくるとAPIや非同期処理が絡んできて、他の人が作成したコードを見てもその内容を理解できないことが多いと思います。
今回は、kintoneの標準機能では行うことのできない「別アプリのテーブル情報を取得する」機能を実現することを念頭に、一緒にアプリを作成していきましょう。
本記事はこのような方におすすめ!
- プログラミング初心者
- kintoneの初歩的なJavaScriptカスタマイズを行ったことがある
- APIや非同期処理を含んだカスタマイズに挑戦したい
アプリの概要
活動記録とプロジェクト管理という2つのアプリを作成します。今回カスタマイズを実装する活動記録の機能は、「活動内容・プロジェクト名などmtgに関するデータを入力し、その記録を一覧で表示する」ということになります。活動記録のアプリでレコードを作成する際、プロジェクト名を入力した際に、プロジェクト管理のアプリを参照して、共有先メンバーを自動的に追加できるようカスタマイズを行います。
2つのアプリのフィールドの詳細は以下のようになります。
活動記録のアプリを作成する際に、プロジェクト名に応じたメンバー情報をテーブル(共有先)にコピーするように設定できれば良いのですが、冒頭でも述べたようにkintoneの標準機能では別アプリのテーブルをコピーすることができません。
では、ここから以下の流れに沿ってJavaScriptのカスタマイズを作成していきましょう。
- 活動記録のテーブル[共有先]に入れる値の種類に応じて、配列変数を用意
- kintone REST API を使用して、プロジェクト管理のテーブル[メンバー]の値を取得し、それぞれの配列変数に要素を追加(get_shareData関数の定義)
- 各配列に全ての要素が入ったら、活動記録のテーブル[共有先]の値を更新(make_result関数の定義/Promiseで処理順序の制御)
1.活動記録のテーブル[共有先]に入れる値の種類に応じて、配列変数を用意
1 2 3 4 5 6 |
kintone.events.on([ 'app.record.create.change.開始日時', 'app.record.edit.change.開始日時'], (event) => { const shareMem = []; const shareDep = []; const shareMail = []; const sharePart = []; |
まず、kintone.events.on() メソッドを使用して、「プロジェクト開始日時」フィールドの値が変更されたときに実行される関数を定義します※。次に氏名・部署・メールアドレス・役割に分けて4つの配列変数を用意します。
※ イベントタイプについて
プロジェクト名が変更された際に共有先テーブルに情報を格納したいので、「レコードの作成・編集時にプロジェクト名が変更された時[‘app.record.create.change.プロジェクト名’, ‘app.record.edit.change.プロジェクト名’]」を指定したくなります。しかし、ルックアップのフィールドはフィールド値変更時イベントで指定できません。そのため、今回はプロジェクト名をルックアップで取得した際にコピーされる別のフィールド”プロジェクト開始日時”を設置し、”プロジェクト開始日時”の値の変更をトリガーにすることにしました。
2.kintone REST API を使用して、プロジェクト管理のテーブル[メンバー]の値を取得し、それぞれの配列変数に要素を追加(get_shareData関数の定義)
get_shareData関数の中で、プロジェクト管理からデータを取得することにします。そのような機能を果たすためにはkintone REST APIを利用することになります。kintone REST APIの基本形は以下のようになります。
kintone.api(pathOrUrl, method, params, successCallback, failureCallback)
各パラメータに何を入れるかは、利用するkintone REST APIに応じて変化します。差し当たって私たち初心者は、methodのパラメータにGET(取得), POST(登録), PUT(更新), DELETE(削除) を指定できることを覚えておきましょう。何ができるのかを理解しておけば、cybozu developer networkのページから基本的な形を参照することができます。
レコードの取得(GET)/レコードの登録(POST)/レコードの更新(PUT)/レコードの削除(DELETE)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
const record = event.record; const proName = record.プロジェクト名.value; const body = { 'app': ”アプリID”, 'query': 'プロジェクト名 = "' + proName + '"', 'fields': ['メンバー'] }; function get_shareData() { kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body, function(resp) { resp.records.forEach(function(record) { const memTable = record.メンバー.value; for (var t = 0; t < memTable.length; t++) { shareMem.push(memTable[t].value.氏名.value); shareDep.push(memTable[t].value.部署.value); shareMail.push(memTable[t].value.メールアドレス.value); sharePart.push(memTable[t].value.役割.value); } }); }); } |
今回は特定のアプリのレコードを条件付けて取得(GET)したいので、レコードの一括取得APIを参考に進めます。基本的には掲載されている形のまま利用できますが、自分でbodyを宣言し、取得したい情報を指定する必要があります。今回はプロジェクト管理において、”プロジェクト名”フィールドに入力したプロジェクトのレコードの、フィールドコードが”メンバー”である部分を指定しています。レコード取得が成功した場合には、1.で用意した配列変数に、得られたテーブルの各要素を追加します。
ちなみにテーブルの値を指定するのがややこしいですが、以下の画像をイメージするとわかりやすいと思います。この例では、フィールドコードが”共有先”のテーブルの3行目、中居さんの役割部分を指定していることになります。
3.共有先テーブルの値を更新
・make_result関数の定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function make_result() { const record = kintone.app.record.get().record; const shareTable = record.共有先.value; while (shareTable.length > 0) { shareTable.splice(0, 1); } for (var i = 0; i <= shareMem.length - 1; i++) { shareTable.push({ value: { "共有者": { value: shareMem[i], type: "SINGLE_LINE_TEXT" }, "部署": { value: shareDep[i], type: "DROP_DOWN" }, "メールアドレス": { value: shareMail[i], type: "LINK" }, "役割": { value: sharePart[i], type: "SINGLE_LINE_TEXT" }, "連絡確認": { value: [], type: "CHECK_BOX" } } }); } kintone.app.record.set({ record: record }); } |
make_result関数では、一旦活動記録のテーブル[共有先]の初期化を行った後、2.で完成した各配列の要素を追加する処理を行なっています。テーブルに要素の追加を行う処理ですが、ここで一つ注意点があります。テーブルに行の追加を行う際は、値だけでなく、必ずフィールドタイプの指定が必要です。文字列(1行)ならSINGLE_LINE_TEXT、数値ならNUMBERのように各々指定する必要があります。この指定を行わないと、エラーが発生するので注意しましょう。
フィールド形式の詳細についてはこちらをご覧ください。
・Promiseで処理順序の制御
REST APIは非同期処理のため、APIの実行が完了する前に後続のコードが走ってしまうことになります。そのため、処理順序を制御することが必要になります。今回は、get_shareData関数の処理が完了してから、make_result関数の処理を実行するようにコードを書く必要があります。
非同期処理を上手に利用することは難しいですが、Promiseの基本的な活用方法を紹介するので、イメージを掴んで頂ければと思います。Promiseオブジェクトは、第一引数にresolve,第二引数にrejectを設定し、resolveした場合にはthenの処理が、rejectした場合にはcatchの処理が走ることになります。第二引数のrejectの設定は任意になります。今回はresolveのみ記述しています。
get_shareData関数内で、各配列変数への要素追加の処理が完了したらresolveとします。2.のコードに以下のようにPromiseの処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function get_shareData() { <em><strong>return new Promise(function(resolve) {</strong></em> kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body, function(resp) { resp.records.forEach(function(record) { const memTable = record.メンバー.value; for (var t = 0; t < memTable.length; t++) { shareMem.push(memTable[t].value.氏名.value); shareDep.push(memTable[t].value.部署.value); shareMail.push(memTable[t].value.メールアドレス.value); sharePart.push(memTable[t].value.役割.value); } <strong><em>resolve();</em></strong> }); }); <strong><em>});</em></strong> } |
そして、thenの処理にmake_result関数を入れます。これで、各々の配列に取得した要素が追加された後に共有先テーブルのデータを更新できるようになります。
1 2 3 |
get_shareData().then(function() { make_result(); }); |
実装したコード全文は以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
(() => { 'use strict'; kintone.events.on([ 'app.record.create.change.開始日時', 'app.record.edit.change.開始日時'], (event) => { const shareMem = []; const shareDep = []; const shareMail = []; const sharePart = []; const record = event.record; const proName = record.プロジェクト名.value; const body = { 'app': ”アプリID”, 'query': 'プロジェクト名 = "' + proName + '"', 'fields': ['メンバー'] }; function get_shareData() { return new Promise(function (resolve) { kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body, function (resp) { resp.records.forEach(function (record) { const memTable = record.メンバー.value; for (var t = 0; t < memTable.length; t++) { shareMem.push(memTable[t].value.氏名.value); shareDep.push(memTable[t].value.部署.value); shareMail.push(memTable[t].value.メールアドレス.value); sharePart.push(memTable[t].value.役割.value); } resolve(); }); }); }); } function make_result() { const record = kintone.app.record.get().record; const shareTable = record.共有先.value; while (shareTable.length > 0) { shareTable.splice(0, 1); } for (var i = 0; i <= shareMem.length - 1; i++) { shareTable.push({ value: { "共有者": { value: shareMem[i], type: "SINGLE_LINE_TEXT" }, "部署": { value: shareDep[i], type: "DROP_DOWN" }, "メールアドレス": { value: shareMail[i], type: "LINK" }, "役割": { value: sharePart[i], type: "SINGLE_LINE_TEXT" }, "連絡確認": { value: [], type: "CHECK_BOX" } } }); } kintone.app.record.set({ record: record }); } get_shareData().then(function () { make_result(); }); return event; }); })(); |
まとめ
以上、Java Scriptを用いて別アプリからデータを取得する方法を紹介しました。
非同期処理に関する制御とREST APIに関する知識を深めて、複雑なカスタマイズにも挑戦してみましょう!!