【kintone】フィールド値更新でハマりがちなこと


こんにちは!
今日は、私がカスタマイズを初めて間もない頃にハマった

「値が表示できないぞ!」

についてです。

別アプリのレコードのデータを使って、フィールド値を更新したいときにハマりがちなところかと思います。
読んでみて、やってみてね!

作りたい目標アプリ

マスターアプリ ドロップダウンで値をとってくる

マスターアプリを作る

マスター?、マスタ?
呼び出し元となるデータを置いとくアプリを作ります。

作り方はかんたん

フィールド種類 フィールドコード
ドロップダウン カテゴリ
文字列(1行) 名前
ドロップダウンの選択肢
文具
おやつ

登録するレコード

カテゴリ 名前
おやつ チョコレート
おやつ プロテイン
文具 鉛筆
文具 消しゴム

↓こんな感じになったらOK

呼び出し側のアプリを作る

フィールド種類 フィールドコード
ドロップダウン カテゴリ(中身はマスターアプリと同じ)
文字列(複数行) 内容

↓こんな感じになったらOK

JavaScriptを書く

それでは、コードを書いていこうと思います。
こちらは呼び出し側アプリのJavaScriptとなります。

フィールド値変更イベントを拾う

↓このあたりを参考に、「カテゴリ」フィールド値変更イベントを拾います。
レコード追加画面のフィールド値変更時イベント
レコード編集画面のフィールド値変更時イベント

↓こんな感じ

(()=>{
    kintone.events.on([
        'app.record.create.change.カテゴリ', //新規・カテゴリフィールド変更イベント
        'app.record.edit.change.カテゴリ' //編集・カテゴリフィールド変更イベント
    ],  event => {
        //ここに処理を書く
        return event;
    });
})();

マスターアプリからレコードを持ってくる

kintone REST API を使って、選択したカテゴリのレコードを一括取得します。
参考:レコードの一括取得(クエリで条件を指定)


        let body = {
            'app': マスターアプリのアプリID,
            //↓これは、ドロップダウンで選択したカテゴリのレコードだけ取ってくるクエリ
            'query':`カテゴリ in("${event.record.カテゴリ.value}")`
        };

        //REST API(GET)を叩いて、データを持ってくる
        kintone.api('/k/v1/records', 'GET', body,(resp)=>{
            //ここで持ってきたデータを処理して、内容フィールドに表示する
        });

取得したデータを処理して、内容フィールドに表示する

        kintone.api('/k/v1/records', 'GET', body,(resp)=>{
            let retStr ="";
            //resp.records内の「名前」フィールドを改行挟んで連結している
            resp.records.forEach(r => {
                retStr +=  r.名前.value + "\n";
            });

            //「内容」フィールドに連結した「名前」を表示する
            event.record.内容.value = retStr;
        });

ひとまずコードが出来上がり。

しかし、これだとうまくいきません

(()=>{

    kintone.events.on([
        'app.record.create.change.カテゴリ', //新規・カテゴリフィールド変更イベント
        'app.record.edit.change.カテゴリ' //編集・カテゴリフィールド変更イベント
    ],  event => {

        let body = {
            'app':  マスターアプリのアプリID,
            //↓これは、ドロップダウンで選択したカテゴリのレコードだけ取ってくるクエリ
            'query':`カテゴリ in("${event.record.カテゴリ.value}")`
        };

        //REST API(GET)を叩いて、データを持ってくる
        kintone.api('/k/v1/records', 'GET', body,(resp)=>{
            let retStr ="";
            //resp.records内の「名前」フィールドを改行挟んで連結している
            resp.records.forEach(r => {
                retStr +=  r.名前.value + "\n";
            });

            //「内容」フィールドに連結した「名前」を表示する
            event.record.内容.value = retStr;
        });

        return event;
    });
})();

ここ変えよう

この部分が思ったように動かない原因となります。

            //「内容」フィールドに連結した「名前」を表示する
            event.record.内容.value = retStr;

理由は・・・
フィールドにデータをセットする前にevent=>{~}が終わっちゃってるからかな・・・。
kintone.api()が非同期なので。レコードにセットする頃にはイベントが終わっちゃってる。だと思います。
//正しい理由がわかる方いらっしゃったら教えて下さい・・・

kintone.api(~)の中ではget&set使ってみよう!

というわけで、
event.recordに直接書き込むのではなく、get&setをつかいます。

            //「内容」フィールドに連結した「名前」を表示する
            let obj = kintone.app.record.get();
            obj.record.内容.value = retStr;
            kintone.app.record.set(obj);

できあがり

(()=>{

    kintone.events.on([
        'app.record.create.change.カテゴリ', //新規・カテゴリフィールド変更イベント
        'app.record.edit.change.カテゴリ' //編集・カテゴリフィールド変更イベント
    ],  event => {

        let body = {
            'app':  マスターアプリのアプリID,
            //↓これは、ドロップダウンで選択したカテゴリのレコードだけ取ってくるクエリ
            'query':`カテゴリ in("${event.record.カテゴリ.value}")`
        };

        //REST API(GET)を叩いて、データを持ってくる
        kintone.api('/k/v1/records', 'GET', body,(resp)=>{
            let retStr ="";
            //resp.records内の「名前」フィールドを改行挟んで連結している
            resp.records.forEach(r => {
                retStr +=  r.名前.value + "\n";
            });

            //「内容」フィールドに連結した「名前」を表示する
            let obj = kintone.app.record.get();
            obj.record.内容.value = retStr;
            kintone.app.record.set(obj);
        });

        return event;
    });
})();

↓こんな感じになりましたでしょうか!?

まとめ

kintone×JavaScriptって、非同期との戦いのことなのかなぁ・・・と思いました。
ちなみに、他のイベント(レコード追加/編集画面の表示後イベントなど)だと、
Promiseオブジェクトをreturnできるので、
getとset使わなくても

return kintone.api(~~~).then(resp=>{
//event.record.内容の値を更新する
return event;
})

で値の更新ができます。
試してみてくださいね!