ルックアップのコピーされるフィールドを変更したら、コピー元アプリを更新する
今回からは、趣向を変えてkintone REST APIを使ったカスタマイズをやってみます。使いこなせるとものすごく強力ですが、やらかすとデータを壊すこともorz
どんなアプリ?
![](https://assets.st-note.com/img/1678964196219-EISLUN3LOR.jpg?width=1200)
こんな感じでマスタから管理番号で氏名をルックアップするものです。
「あれ?ルックアップのコピー先フィールドなのに入力ができる……そうなんです。
![](https://assets.st-note.com/img/1678964757311-ZAvD8mAcxg.jpg)
こんなことができちゃいます。ではやってみましょう。
出来上がりのアプリのテンプレートを置いています。後述しますが、JavaScriptを書き換えないと動作しませんのでご注意を。
強敵Promiseの登場
kintone REST APIが出始めると姿を表し始める強敵……、それがPromiseです。自分のようなプログラム初心者にとっては、「命令は順番に実行される」方が簡単なんですが、Webの世界では実際は色々な作業が並行して行われてます。例えば、「画像が全て読み込まれるまで一切操作ができないウェブページ」とか、かなりイライラしそうです。
作業が「成功」「失敗」「今真っ最中!」みないな状態を管理してくれるのがPromiseで、「処理が終わるまで待つ」っていうのが、とりあえずの使い方になります(使いこなすと、「並行して5つの仕事して全部終わったら次に進む」なんてことも可能ですが、kintoneのカスタマイズではあまり使わないかも)。
自分はごく最近に勉強し始めたのでasync/awaitという比較的新しい仕組みを使ってます。ホントはきちんと勉強したほうがいいんだろうなぁ……
作ったコード
ルックアップ_データの方に設定します。
あ、分かりやすくするために、エラー処理等は取っ払ってます。もしこのコードを何かに応用しようなんて場合はご注意ください。
(() => {
('use strict');
const appData = 237;
const appMaster = 238;
kintone.events.on(
[
'app.record.create.show',
'app.record.edit.show',
'app.record.index.edit.show',
],
(event) => {
// 氏名フィールドを編集可能にする
const items = ['氏名'];
const record = event.record;
items.forEach((item) => (record[item].disabled = false));
return event;
},
);
// 氏名フィールドを更新
kintone.events.on(
['app.record.create.submit', 'app.record.edit.submit'],
async (event) => {
const record = event.record;
// マスタから同じ管理番号のデータを取得する
const searched = await kintone.api('/k/v1/records.json', 'GET', {
fields: ['管理番号', '氏名'],
app: appMaster,
query: `管理番号 = "${record.管理番号.value}"`,
totalCount: true,
});
// 氏名が同じ(変更がない)ときと取得件数が1件以外のときは処理を終える
if (
searched.totalCount != 1 ||
searched.records[0].氏名.value === record.氏名.value
) {
return event;
}
// マスタの氏名を更新する
await kintone.api('/k/v1/record.json', 'PUT', {
app: appMaster,
updateKey: {
field: '管理番号',
value: searched.records[0].管理番号.value,
},
record: {
氏名: { value: record.氏名.value },
},
});
window.alert('氏名変更をマスタに反映させました。');
return event;
},
);
})();
こんな感じです。読み込み後と保存時にコードが走ります。
アプリを開いたら、氏名フィールドを編集可能にする
kintone.events.on(
[
'app.record.create.show',
'app.record.edit.show',
'app.record.index.edit.show',
],
(event) => {
// 氏名フィールドを編集可能にする
const items = ['氏名'];
const record = event.record;
items.forEach((item) => (record[item].disabled = false));
return event;
},
);
本来は編集できないルックアップコピー先フィールドを編集可能にしています。実は、こうすると、フィールドを変更して保存できちゃうんです。これを使って「郵便番号で住所をルックアップした後に、丁番を追記する」なんてことも可能です(まあ、別フィールドに保存すれば?ってのはありますが)。
ちなみに、itemsに複数のフィールドを記載すれば、まとめて編集可能にできます。コピー先フィールドが複数の場合などに使えそうです。
保存時① マスタから同じ管理番号の氏名を取得してくる
const appData = 237;
const appMaster = 238;
まず最初に、データアプリ、マスタアプリのアプリ番号を定数に定義しています。この部分は、一人ひとり違うアプリ番号になるので、調べて書き換えてください。
kintone.events.on(
['app.record.create.submit', 'app.record.edit.submit'],
async (event) => {
const record = event.record;
// マスタから同じ管理番号のデータを取得する
const searched = await kintone.api('/k/v1/records.json', 'GET', {
fields: ['管理番号', '氏名'],
app: appMaster,
query: `管理番号 = "${record.管理番号.value}"`,
totalCount: true,
});
// 氏名が同じ(変更がない)ときと取得件数が1件以外のときは処理を終える
if (
searched.totalCount != 1 ||
searched.records[0].氏名.value === record.氏名.value
) {
return event;
}
見慣れないasyncが入ってきました。このコマンドはawaitと対になってまして、「asyncが宣言されたブロック内にawaitが出ると、その処理が終わるのを待って次に進む」といった挙動になります。いろんな処理にawaitを書いても動いてはくれますが、ただの無駄なので「必要な非同期処理」にのみ書くようにしましょう。
管理番号でマスタアプリを検索し、
見つかったデータ個数が1個ではない場合(基本的には無いが、エラー対策)
見つかったレコードの氏名が同じ場合(書き換えが不要な場合)
は処理を終了するようにしています。
// マスタの氏名を更新する
await kintone.api('/k/v1/record.json', 'PUT', {
app: appMaster,
updateKey: {
field: '管理番号',
value: searched.records[0].管理番号.value,
},
record: {
氏名: { value: record.氏名.value },
},
});
window.alert('氏名変更をマスタに反映させました。');
return event;
マスタに氏名が異なるデータが1個だけ見つかったら、データの氏名に書き換えています。ここでもawaitが出てきています。とりあえず、kintone REST APIを使うときは、基本的に「処理が終わるのを待たせる」必要があると意識しているといいと思います(結果的に、待たなくてもうまくいくことはあるけど、危うい)。
ここまで書きましたが……
サイボウズ社は、こんな親切な研修を不定期に開いてくれています。実は、自分はこれをきっかけにJavaScriptが少しづつ分かるようになってきました。うまくタイミングが合えば、まずはこちらを受講することをおすすめします。