Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
37
Help us understand the problem. What are the problem?

kintone JavaScript カスタマイズ CheatSheet

kintone カスタマイズをする際によく使うコードを集めてみました。

JavaScript

DOM操作

テキストボックスとボタンの生成

        // テキストボックスとボタンを生成
        let newText = document.createElement('input');
        newText.type = 'text';
        newText.id = 'text1';
        let newButton = document.createElement('button');
        newButton.id = 'button1';
        newButton.innerText = '検索';
        kintone.app.getHeaderMenuSpaceElement().appendChild(newText);
        kintone.app.getHeaderMenuSpaceElement().appendChild(newButton);
        // ボタンクリックイベント
        newButton.addEventListener('click', function(){
           console.log(newText.value); 
        });

スペースに jQueryでボタンを設置する

index.js
(function($){
    // 3. ボタン要素をJavaScriptで作成する。
    var objButton = function(elm){$(elm).append('<button id="kintone-event-test-button">ボタン</button>')};
    kintone.events.on('app.record.detail.show', function(){
        console.log('ボタン作成関数');
        // 2. kintone JavaScriptカスタマイズにて、kintone JavaScript API の [kintone.app.record.getSpaceElement(id)](https://developer.cybozu.io/hc/ja/articles/201942014#step6) 関数で、スペースフィールド[button]の要素を取得する。
        var elmButton = kintone.app.record.getSpaceElement('button');
        console.log('ボタン要素 => ', elmButton);
        // 4. 取得した要素に3.で作成したボタン要素を追加する。
        objButton(elmButton);
        // 5. ボタンを押した時に何かする処理を入れる。
        $('#kintone-event-test-button').on('click', function(){alert('Hi!')});
    });
})(jQuery);

kintone

kintone JavaScript API

kintoneのフロント側の処理に利用する標準APIです。
https://developer.cybozu.io/hc/ja/articles/360000361686

情報取得

  • アプリのIDを取得する
var appId = kintone.app.getId();
  • 現在開いているアプリのレコードIDを取得する
const recordId = kintone.app.record.getId();

詳細画面

詳細の空白スペースにボタンを設置する

kintone.app.record.getHeaderMenuSpaceElement().appendChild(myDetailButton);

フィールド要素取得

kintone.app.record.getFieldElement(myFieldEl);

スペースフィールドの要素を取得

kintone.app.record.getSpaceElement(mySpaceEl);

詳細画面のメニューの上側の空白部分にボタンを設置

kintone UI Component 利用

(function() {
    "use strict";
    /**
     * レコード詳細画面表示イベント 
     *
    */
    var kintoneEvent;
    (function () {
      kintone.events.on("app.record.detail.show", function (event) {
        kintoneEvent = event;
        var kintoneSpaceElement = kintone.app.record.getHeaderMenuSpaceElement();
        var button = new kintoneUIComponent.Button({ text: 'Submit' });
        console.log(button);
        kintoneSpaceElement.appendChild(button.render());

        button.on('click', function(e){
          viewAlert(kintoneEvent);
        });

        // 処理が少ない時は直接ここに書いても良い。
        // button.on('click', function(e){
        //   alert('kintone event =>' + e);
        // });

      });
    })();

    // イベントハンドラを受けての処理を記述
    var viewAlert = e => alert('kintone event =>' + e);

})();

一覧画面

一覧の空白スペースにボタンを設置する

kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);

アプリアクション

アプリアクションの動作をプログラムから実行する。

  • action=<アプリアクションID>

アプリアクションIDは、2021年3月のアップデートで追加された、APIから取得しても良い。
アプリのアクション設定の取得

(function() {
  'use strict';
  kintone.events.on('app.record.detail.show', function(event) {
    const ref = kintone.app.record.getFieldElement('関連レコード一覧');
    ref.addEventListener('click', () => {
      const recordId = kintone.app.record.getId();
      window.open(`https://subdomain.cybozu.com/k/123/edit?action=12345678&app=123&record=${recordId}`, '_blank');
    });
    return event;
  });
})();

フィールドの設定を変更する

ドロップダウンフィールドの項目を追加する

var body = {
  'app': kintone.app.getId(),
  'properties': {
    "ドロップダウン": {
      "type": "DROP_DOWN",
      "code": "ドロップダウン",
      "label": "ドロップダウン",
      "noLabel": false,
      "required": false,
      "options": {
        "sample1": {
          "label": "sample1",
          "index": "0"
        },
        "sample2": {
          "label": "sample2",
          "index": "1"
        },
        "sample3": {
          "label": "sample3",
          "index": "2"
        }
      },
      "defaultValue": ""
    },
  }
};

kintone.api(kintone.api.url('/k/v1/preview/app/form/fields', true), 'PUT', body, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});

var body = {
  'apps': [
    {
      'app': kintone.app.getId()
    },
  ]
};

kintone.api(kintone.api.url('/k/v1/preview/app/deploy', true), 'POST', body, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});

kintone REST API

kintoneのデータベース(いわゆるアプリ)にREST形式でアクセスするAPI群です。
https://developer.cybozu.io/hc/ja/articles/360000313406


"kintone REST API" の利用方法

利用方法には大きく以下の2つの方法があります。

  1. kintone内部からのアクセス
    1.1 kintone.api() 関数を利用する。
    1.2 kintone.proxy() 関数を利用する。

  2. kintone外部からのアクセス
    2.1 curlやその他プログラム言語からHTTPSを利用してよしなにアクセスする。

kintoneの内部から普通に利用する場合は、1.1のkintone.api()関数からREST APIを利用すれば良いです。
kintone.proxy()は、kintone内部から外部のAPIにアクセスする場合と、例えばログインユーザーにアプリ管理権限
が無い場合に実行にアプリ管理権限が必要なAPIを利用する場合に、アプリのアクセス権限が付与されたAPIトークンを利用してproxyサーバー経由でアクセスする場合にも利用します。

上記のproxyアクセスは、例えばアプリのアクセス権の取得APIをアプリの管理権限が無いユーザーが実行したい場合などが考えられます。
その場合は、対象アプリからアプリの管理権限が付与されたAPIトークンを取得して、kintone.proxy()経由でアクセスします。
kintone.proxy()を利用する場合は、APIトークンや外部APIへの認証情報を直接JSに埋め込まない様に注意が必要です。
https://developer.cybozu.io/hc/ja/articles/201919400#step8

アプリの設計情報取得

コーディング時、アプリのフィールドコードを確認する際にChromeDevToolのコンソールに貼り付けて使ってます。("app": の後にアプリIDを入力します)

kintone.api(kintone.api.url('/k/v1/form', true), 'GET', {"app": kintone.app.getId()}, function(resp) {
    // success
    console.log(resp);
    console.log(JSON.stringify(resp));
}, function(error) {
    // error
    console.log(error);
});

フォーム設定取得

アプリのフォームの設定を取得します。
主に、プラグインの作成時、仕様書を起こす際のレコードレイアウト作成時に使っています。

var body = {
    "app": kintone.app.getId()
};
kintone.api(kintone.api.url('/k/v1/app/form/fields', true), 'GET', body, function(resp) {
    // success
    console.log(JSON.stringify(resp, null, 2));
}, function(error) {
    // error
    console.log(error);
});

フォーム設定取得からフィールドコードを抜き出す

前段のAPIから出力した結果をform-fields.jsonに保存したとき。

$ cat form-fields.json | jq '.properties | keys'

または、

$ cat form-fields.json | jq '.properties[] | .code'

フォームレイアウト取得

フォームのレイアウトを取得する

var body = {
    "app": kintone.app.getId()
};

kintone.api(kintone.api.url('/k/v1/app/form/layout', true), 'GET', body, function(resp) {
    // success
    // console.log(resp);
    console.log(JSON.stringify(resp, null, 2)); // JSONを整形して出力
}, function(error) {
    // error
    console.log(error);
});

アプリ

アプリ情報の一括取得

アプリ情報を一括取得します。(最大100件)

100件取得

kintone.api(kintone.api.url('/k/v1/apps', true), 'GET', {}, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});

次の100件

kintone.api(kintone.api.url('/k/v1/apps', true), 'GET', {offset:100}, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});

スペース

スペース情報の取得

スペース内アプリ一覧等が取得出来ます。
kintoneのスペースを開いた状態で、DevTools等のコンソールで実行します。

kintone.api(kintone.api.url('/k/v1/space', true), 'GET', {"id": 1}, function(resp) {
    // success
    // console.log(resp);
    console.log(JSON.stringify(resp, null, 2));
}, function(error) {
    // error
    console.log(error);
});

スペース内アプリ一覧

取得したJSONを使ってスペースのアプリIDとアプリ名を取り出してみる。

まず上記で取得したJSONをファイルに保存して(space.jsonなど)

そのまま出力
$ cat space.json | jq

スペース内のアプリ一覧情報は "attachedApps: []" にあるので抽出
$ cat space.json | jq '.attachedApps'

配列から外して
$ cat space.json | jq '.attachedApps | .[]'

"appId"のみ抽出
$ cat space.json | jq '.attachedApps | .[] | .appId'

配列に入れたり
$ cat space.json | jq '.attachedApps | .[] | [.appId]'

オブジェクトに入れたり
$ cat space.json | jq '.attachedApps | .[] | {appId: .appId}'
$ cat space.json | jq '.attachedApps | .[] | {appId: .appId, name: .name}'

アプリIDとアプリ名を抽出して配列にして
$ cat space.json | jq '.attachedApps | .[] | [.appId, .name]'

最後にCSVに出力
$ cat space.json | jq '.attachedApps | .[] | [.appId, .name] | @csv'

-r オプション付けて
$ cat space.json | jq -r '.attachedApps | .[] | [.appId, .name] | @csv'

.nameでソートする
cat apps.json | jq -r '.attachedApps | sort_by(.name) | .[] | [.name, .appId] | @csv' > apps.csv

参考:
https://jqplay.org/

レコード

レコード1行取得

kintone REST API で取得されるレコードレイアウト確認に使ってます。

var body = {
    "app": 1,
    "id": 1001
};
kintone.api(kintone.api.url('/k/v1/record', true), 'GET', body, function(resp) {
    // success
    console.log(resp);
}, function(error) {
    // error
    console.log(error);
});
var body = {
    "app": kintone.app.getId(),
    "id": kintone.app.record.getId()
};

kintone.api(kintone.api.url('/k/v1/record', true), 'GET', body, function(resp) {
    // success
    console.log(resp);
}, function(error) {
    // error
    console.log(error);
});

現在開いているアプリとレコードが対象の時は、アプリIDとレコードIDをAPIでセットしても良い。

良い感じでJSONを整形する

var body = {
    "app": kintone.app.getId(),
    "id": kintone.app.record.getId()
};

kintone.api(kintone.api.url('/k/v1/record', true), 'GET', body, function(resp) {
    // success
    console.log(JSON.stringify(resp, null, 4));
}, function(error) {
    // error
    console.log(error);
});

レコード一括取得(クエリ指定)


var body = {
    "app": 1,
    "query": "updated_time > \"2012-02-03T09:00:00+0900\" and updated_time < \"2012-02-03T10:00:00+0900\" order by $id asc limit 10 offset 0",
    "fields": ["$id", "created_time", "dropdown"]
};

kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body, function(resp) {
    // success
    console.log(resp);
}, function(error) {
    // error
    console.log(error);
});

一覧のクエリ文字列を取得する


var condition = kintone.app.getQueryCondition();
console.log(condition);

// order by, limit, offset付きで取得する場合はこちら
var condition = kintone.app.getQuery();
console.log(condition);

開発者ツールのコマンドラインから打ち込むと、下記のように一覧画面の検索条件がクエリ文字列で表示されるので便利です。

"更新日時 > FROM_TODAY(-2, DAYS) order by 更新日時 desc limit 100 offset 0"

アプリアクション時にルックアップの取得を自動で行う

(function() {
  'use strict';
  kintone.events.on('app.record.create.show', function(event) {
    const record = event.record;
    record[<ルックアップのフィールドコード>].lookup = true;
    return event;
  });
})();

record[<ルックアップのフィールドコード>]['lookup'] = 'UPDATE'
でも同じ

フィールドのchangeイベントで書き換えられた値を別フィールドにセットする


(function() {
    "use strict";
    kintone.events.on(["app.record.edit.change.日付", "app.record.create.change.日付"], function(event) {

        console.log(event);
        let changesValue = event.changes.field.value;
        console.log(changesValue);
        let record = event.record;
        // var record = kintone.app.record.get();
        // record.record['最新日付'].value = '書き換えた文字列';
        // kintone.app.record.set(record);
        // changes.field.value
        record['最新日付'].value = changesValue;
        return event;
    });
})();

bulkRequest バルクリクエスト

複数のアプリに対して、同時に複数の APIをリクエストすることが出来ます。

  • 最大20リクエストまで
  • いずれかのAPI失敗で、全部がロールバックされます
  • パスワード認証で使うが、単一アプリIDへのリクエストならAPIトークン可
  • ゲストスペースは注意。同一ゲストスペース内のアプリの処理のみ可能
URI https://subdomain.cybozu.com/k/v1/bulkRequest.json
POST
{
  "requests": [
    {
      "method": "POST",
      "api": "/k/v1/record.json",
      "payload": {
        "app": 365,
        "record": {
          "文字列1": {
            "value": "文字列__1行を追加します。"
          }
        }
      }
    },
    {
      "method": "PUT",
      "api": "/k/v1/record.json",
      "payload": {
        "app": 369,
        "id": 1,
        "record": {
          "文字列1": {
            "value": "文字列__1行を更新します。"
          }
        }
      }
    }
  ]
}
(function() {
    "use strict";
    kintone.events.on("app.record.index.show", function(e) {
        // バルクリクエスト発火用のボタンを設置
        var newButton2 = document.createElement('button');
        newButton2.id = 'button1';
        newButton2.innerText = 'バルクリクエスト';
        kintone.app.getHeaderSpaceElement().appendChild(newButton2);
        newButton2.addEventListener('click', function(){
            doBulkRequest();
        });
    });
    var doBulkRequest = function(){
        var body = {
          "requests": [
            {
              "method": "POST",
              "api": "/k/v1/record.json",
              "payload": {
                "app": 365,
                "record": {
                  "文字列1": {
                    "value": "文字列1行とテーブル2行追加"
                  },
                  "Table": {
                      "value": [
                          {
                              "id": 1,
                              "value": {
                                  "文字列": {
                                      "value": "テーブルテスト1行目"
                                  }
                              }
                          },
                          {
                              "id": 2,
                              "value": {
                                  "文字列": {
                                      "value": "テーブルテスト2行目"
                                  }
                              }
                          }
                      ]
                  }
                }
              }
            },
            {
              "method": "PUT",
              "api": "/k/v1/record.json",
              "payload": {
                "app": 369,
                "id": 2,
                "record": {
                  "文字列1": {
                    "value": "文字列1行を更新。"
                  },
                  "文字列2": {
                    "value": "文字列2行を更新。"
                  },
                  "Table": {
                      "value": [
                          {
                              "id": 1,
                              "value": {
                                  "文字列": "テーブル内1行目文字列を更新"
                              }
                          },
                          {
                              "id": 2,
                              "value": {
                                  "文字列": "テーブル内2行目文字列を更新"
                              }
                          }
                    ]
                  }
                }
              }
            }
          ]
        }
        kintone.api(kintone.api.url('/k/v1/bulkRequest', true), 'POST', body, function(resp) {
            //success
            console.log(resp);
        }, function(error) {
            //error
            console.log(error);
        });
    }
})();


cybozu.com

User API

ユーザーエクスポート API(JSON)

kintone.api(kintone.api.url('/v1/users', true), 'GET', {}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});

ユーザーの所属組織エクスポート API(JSON)

kintone.api(kintone.api.url('/v1/user/organizations', true), 'GET', {code:"<ユーザーコード>"}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});

ユーザーの所属グループエクスポート API(JSON)

kintone.api(kintone.api.url('/v1/user/groups', true), 'GET', {code:"<ユーザーコード>"}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});

curl による kintone API アクセス

利用方法について
シェルスクリプトと同じディレクトリにkintone APIに渡す認証情報を .env ファイルに記述します。

apitoken="<APIトークン>"

アプリのアクセス権の取得(/k/v1/app/acl.json)

https://developer.cybozu.io/hc/ja/articles/204529754
アプリの設定のアクセス権で設定した、ユーザー/組織/グループごとに設定したアプリの権限をJSONで取得できます。

app_acl.sh
#!/bin/bash

source ./.env
APITOKEN=${apitoken}
APPID=${appid}
SUBDOMAIN=${subdomain}
curl -X GET -H "X-Cybozu-API-Token:${APITOKEN}" "https://${SUBDOMAIN}.cybozu.com/k/v1/app/acl.json?app=${APPID}"

jQuery

jQuery

要素を指定して自身の要素を含んだHTMLを取得する

const html = `
<div class="content">
  <div id="title" >
    <p>テスト</p>
  </div>
</div>
`;
console.log($(html).find('#title').prop('outerHTML'));

// 結果
//<div id="title">
//    <p>テスト</p>
//  </div>

jQueryの引数に変数を渡して展開する

const id = 'title'
console.log($(html).find(`#${id}`).prop('outerHTML'));

jQueryの内側の要素を置き換える

const html = `
<div class="content">
  <div id="title" >
    <p>テスト</p>
  </div>
</div>
`;
const replace = `
<div id="title2" >
  <p>テスト2</p>
</div>
`;
console.log($(html).html(replace).prop('outerHTML'))

//結果
//<div class="content">
//<div id="title2">
//  <p>テスト2</p>
//</div>
//</div>

jQueryのセレクタで取得した配列についてプロパティ指定でid名を取得する

const Html = `
<div class="main_content">
  <div id="title" class="content_box">
    <p>タイトル</p>
  </div>
  <div id="sub_title" class="content_box">
    <p>サブタイトル</p>
  </div>
</div>
`
function fetchPortalMenuIdes(html, selector) {
  return  $(html).find(selector).map(function(i, v){return $(this).prop('id')});
  // return  $(html).find(selector).map(function(i, v){return $(this).attr('id')}); // attrでも同じ結果
  // return  $(html).find(selector).map((i, v) => {return $(v).prop('id')}); // 無名関数もOK
}
console.log(fetchPortalMenuIdes(Html, 'div.content_box')); // jQueryオブジェクトが返る
console.log(fetchPortalMenuIdes(Html, 'div.content_box').get()) // JavaScript配列が返る;

// 結果
// S {
//  0:"title",
//  1:"sub_title",
// }
// ["title","sub_title"]

関数をカリー化する

function fetchPortalMenuIdes(html) {
  return (selector) => {
    return  $(html).find(selector).map(function(i, v){return $(this).prop('id')}).get();
  }
}
console.log(fetchPortalMenuIdes(Html)('div.content_box'));
console.log(fetchPortalMenuIdes(Html)); // 内側の関数が返る

jQuery UI

ダイアログ


<script src="https://js.cybozu.com/jquery/2.2.4/jquery.min.js"></script>
<script src="https://js.cybozu.com/jqueryui/1.12.0/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://js.cybozu.com/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">

var compiled = _.template('<div id="dialog" title="Hello"> Hello,<%= echo %></div>')({echo: 'World'});
var elMyBt = _.template('<button id="myBt">click</button>');
$(kintone.app.record.getHeaderMenuSpaceElement()).append(elMyBt);
$('#myBt').on('click', function() {
    viewDialog();
});
function viewDialog() {
    $(compiled).dialog({autoOpen: false, modal: true}).dialog('open');
}

JavaScript

関数

関数を作る


function square(number) {
  return number * number;
}

クラスを作る

var SampleLib = (function () {
  'use strict';

  // コンストラクタ
  function SampleLib() {
  }

  SampleLib.prototype.hello = () => {
    return 'Hello from kintone CLI';
  }

  return SampleLib;
})();

呼び出し側

(function () {
  'use strict';
  kintone.events.on('app.record.index.show', function (event) {
    const samplelib = new SampleLib(); // インスタンス生成
    console.log(samplelib.hello());
    return event;
  });
})();

Promise


var funcA = function promiseSampleA() {
                // Promiseを返す処理A
            };
var funcB = function promiseSampleB() {
                // Promiseを返す処理B
            };
function main() {
    return Promise.all([promiseSampleA(), promiseSampleB()]);
}
// 実行例
main().then(function (value) {
    console.log(value);
}).catch(function(error){
    console.error(error);
});

kintone.Promise()

  kintone.events.on('<kintoneイベント>', (event) => {
    return new kintone.Promise((resolve) => {
      // 何か処理
      resolve(<次に渡したい結果など>); // Promiseチェーンで繋げたい結果はresolve()で返却する
    })
    .then(result => {
      // 何か処理
      // REST APIでレコードを取得など。 下記の書き方をすれば、処理結果がPromiseで返される。
      return kintone.api(kintone.api.url('<REST API エンドポイント>', true), '<GET/POST>', <パラメータ>);
    })
    .then(result => {
      // 何か処理
      return event; // 結果をレコードに反映するなどの処理に応じて、最後にeventをリターンする。
    })
    .catch(error => {
      console.error(error);
    });
  });

undefined 判定

var foo = {'name': "bar"};
console.log('foo.name =>', foo.name); // foo.name => bar
console.log('foo.value =>', foo.value); // foo.value => undefined
if (typeof foo.value === 'undefined') {
    console.log('foo.value of undefined');
}

オブジェクトの値でソートして、オブジェクトのキーの配列を返す

const obj = {
  test01:900,
  test03:2,
  test02:1,
  test04:3000,
  test05:4
}
console.log(obj);
const sortedKeys = Object.keys(obj).sort((a, b) => {
  return obj[a] - obj[b]
});
console.log(sortedKeys); //  ["test02","test03","test05","test01","test04"]

複数の配列を1つの配列に展開して、重複を取り除いた配列を返す

const menus1 = ['test01', 'test03']
const menus2 = ['test01', 'test02', 'test04', 'test05']
const flattenedMenus = [menus1, menus2].reduce(
  ( accumulator, currentValue ) => accumulator.concat(currentValue),
  []
).reduce(function (accumulator, currentValue) {
  if (accumulator.indexOf(currentValue) === -1) {
    accumulator.push(currentValue)
  }
  return accumulator
}, [])
console.log('flattenedMenus =>', flattenedMenus);
// flattenedMenus => ["test01","test03","test02","test04","test05"]
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
37
Help us understand the problem. What are the problem?