kintoneプラグイン開発をはじめよう②設定画面の作り方

# この記事のターゲット
- プラグイン開発初心者
- [kintoneプラグイン開発をはじめよう①](https://qiita.com/asami_/items/724e4f2bef9b0ce8e28c)の記事が読み終わった人

# この記事のゴール

- プラグイン設定画面の作り方がわかる！


# プラグインの設定画面

kintoneのカスタマイズでは、アプリによって変わる値（フィールドコードやアプリIDなど）もベタ書きしています。そのため、別アプリに同じカスタマイズを適用しようとするとき、フィールドコードを揃えたり、JSのコードを書き換えたりする必要が出てきます。

プラグインでは、そんな「アプリや環境によって変わる情報」を設定画面でユーザーが設定可能にすることで、さまざまなアプリで利用がしやすいように作ることができます。

ということで、プラグインは設定画面が大事ですね！

## 設定画面に必要なファイル

create-plugin で作ったサンプルプラグインの場合は、以下のファイルが用意されています。

- html/config.html
- css/config.css
- js/config.js

設定画面の大元になるHTMLと、見た目を整えるためのCSS、設定画面の動きを作るためのJavaScriptです。

これらのファイルは、すべて manifest.json の``config``で定義されています。

```json:manifest.json（抜粋）
  "config": {
    "html": "html/config.html",
    "js": [
      "https://js.cybozu.com/jquery/3.3.1/jquery.min.js",
      "js/config.js"
    ],
    "css": [
      "css/51-modern-default.css",
      "css/config.css"
    ],
    "required_params": [
      "message"
    ]
  }
```

プラグインの設定画面は、初期状態ではまっさらです。真っ白です。何もありません。
その真っ新なHTMLに自分で要素（入力フィールドや選択肢、保存ボタンなど）を書いて、JavaScriptで動きを制御していくため、HTMLの要素を扱いやすいjQueryを使うことが多いです。
CDNを使う場合は、このサンプルのようにURLを書きましょう。

```json:manifest.json（抜粋）
    "js": [
      "https://js.cybozu.com/jquery/3.3.1/jquery.min.js",
      "js/config.js"
    ]
```

なお、プラグインで利用するファイルのファイル名やフォルダ構造は変えることができます。
「manifest.json」ファイルには、「manifest.json」の位置からのファイルパスを記載してください。
サンプルプラグインの場合は、
src
├ manifest.json
└ js
　└ confis.js
というフォルダ構造なので、manifest.jsonでは``js/config.js``と記載されています。
ファイル名やフォルダ構造を変える時は、manifest.jsonファイルの内容も忘れずに変更してください。



## html/config.html

設定画面のHTMLファイルは、bodyの中身だけを記載します。
前述した通り、初期状態は真っ白です。自由に作れます。
大抵は以下の内容を載せます。

- プラグインのタイトル
- プラグインの設定項目（入力フィールドや選択フィールド）
- 保存ボタン
- キャンセルボタン
![config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197668/d1843f04-302b-155b-a12a-4cabdfcd07d0.png)

基本的には好きなように書いて大丈夫です。
自信がない人はサンプルのHTMLを改変していくと綺麗に書けると思います。

- 入力フォームなので、``form``タグを使っておくと制御しやすい
- CSSやJSで制御しやすいようにclass名をつけたりid名をつける

サンプルプラグインのHTMLは以下の通りです。(2021/12/17現在）

```html:html/config.html
<section class="settings">
  <h2 class="settings-heading">Settings for hello-kintone-plugin</h2>
  <p class="kintoneplugin-desc">This message is displayed on the app page after the app has been updated.</p>
  <form class="js-submit-settings">
    <p class="kintoneplugin-row">
      <label for="message">
        Message:
        <input type="text" class="js-text-message kintoneplugin-input-text">
      </label>
    </p>
    <p class="kintoneplugin-row">
        <button type="button" class="js-cancel-button kintoneplugin-button-dialog-cancel">Cancel</button>
        <button class="kintoneplugin-button-dialog-ok">Save</button>
    </p>
  </form>
</section>
```

### 設定画面の項目を入力必須にする

html/config.html 8行目のinputタグに ``requrired``を追加してみてください。

```HTML
<input type="text" class="js-text-message kintoneplugin-input-text" required>
```

こうすると、設定の保存時に「Message」が未入力だったら、エラーが表示されて保存できません。
この動きはinputタグのrequired属性を使った動きです。
![required.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197668/a8334ce3-500d-ca50-9476-21a6eea5182e.png)
ブラウザによって表示は若干異なります。↑はEdgeです。
こういった制御を入れないと、「必須項目にしておきたいのに保存できちゃった」ということが起きてしまうので注意が必要です。

このほかに、manifest.jsonでも必須入力の制御を行います。

```json:manifest.json（抜粋）
  "config": {
    "html": "html/config.html",
    "js": [
      "https://js.cybozu.com/jquery/3.3.1/jquery.min.js",
      "js/config.js"
    ],
    "css": [
      "css/51-modern-default.css",
      "css/config.css"
    ],
    "required_params": [
      "message"
    ]
  }
```

config の最後の`` required_params ``です。
ここに入力必須の項目を設定しておくと、必須項目を設定していない時、設定画面やアプリの利用画面で警告が表示されます。
![required-manifest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197668/f979c9ed-4531-7bd7-d529-88b9da8ad3fd.png)
![required-manifest-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197668/a04486b4-a895-3074-6528-e9613efec473.png)

「アプリにプラグインを入れただけで何も設定してない」という状態の時、この警告を出しておけば管理者が忘れずにプラグインの設定をしてくれます。
また、「必要な情報が設定されていないのにプラグインが動いてしまった」ということも防げます。

manifest.jsonのrequired_paramsに設定する項目名（例では"message"）については、後述のconfig.jsの解説で説明します。

## css/config.css

設定画面を装飾するためのCSSファイルです。
create-pluginのサンプルプラグインでは以下の内容になっています。

```css:config.css
.settings-heading {
  padding: 1em 0;
}

.kintoneplugin-input-text {
  width: 20em;
}
```

シンプル！

kintone　の見た目に近づける部分は、サイボウズが提供している「[51-modern-default.css](https://developer.cybozu.io/hc/ja/articles/203302214)」を利用しています。
「[51-modern-default.css](https://developer.cybozu.io/hc/ja/articles/203302214)」の利用例のように、設定画面のHTMLで指定のclassを用いることで、kintoneに近い見た目を再現することができます。


## js/config.js

設定画面用のJavaSciriptファイルを見ていきましょう。
サンプルプラグインでは、以下の内容です。

```javascript:js/config.js
jQuery.noConflict();

(function($, PLUGIN_ID) {
  'use strict';

  var $form = $('.js-submit-settings');
  var $cancelButton = $('.js-cancel-button');
  var $message = $('.js-text-message');
  var config = kintone.plugin.app.getConfig(PLUGIN_ID);

  if (config.message) {
    $message.val(config.message);
  }
  $form.on('submit', function(e) {
    e.preventDefault();
    kintone.plugin.app.setConfig({message: $message.val()}, function() {
      alert('The plug-in settings have been saved. Please update the app!');
      window.location.href = '../../flow?app=' + kintone.app.getId();
    });
  });
  $cancelButton.on('click', function() {
    window.location.href = '../../' + kintone.app.getId() + '/plugin/';
  });
})(jQuery, kintone.$PLUGIN_ID);
```

ここでは、注目すべき５つのポイントについて解説していきます。

### ポイント１：即時関数の書き方

kintone カスタマイズでは、以下のように即時関数で処理を書きますね。

```javascript:カスタマイズ
(function() {
  // 処理を書く

})();
```

プラグイン用のJavaScirptは、以下のようになります。

```javascript:プラグイン（config.js）
(function(PLUGIN_ID) {
  // 処理を書く

})(kintone.$PLUGIN_ID);
```
``kintone.$PLUGIN_ID`` に、システムで一意で割り当てられるプラグインIDが入ってきます。
これは後ほど、プラグインの設定情報を取得するときに使います。
最初は意味がよくわからなくても、「プラグインではこの書き方をする」と覚えておけば大丈夫です。

ところで、サンプルプラグインのconfig.jsは以下のようになっていますね。

```javascript:プラグイン（config.js）
jQuery.noConflict();

(function($, PLUGIN_ID) {
  // 処理を書く

})(jQuery, kintone.$PLUGIN_ID);
```

これはjQueryを使っているためです。
jQueryの使いかたが不安な人は、「[はじめよう kintone API 第12回 jQuery を利用してみよう](https://developer.cybozu.io/hc/ja/articles/204695384)」を振り返ってみてください。

※他のプラグインやカスタマイズでjQueryを使っているとjQueryが競合してしまうことがあるので、コードの頭に``jQuery.noConflict();``を付けるのも忘れずに。

### ポイント２：プラグインの設定情報を保存する

設定画面で入力した値は、プラグインの設定として保存する必要があります。
このときに使うのが、 [kintone.plugin.app.setConfig()](https://developer.cybozu.io/hc/ja/articles/203661160#step2) です。

```javascript
kintone.plugin.app.setConfig(config, successCallback);
```

サンプルプラグインでは次のようになっています。

```javascript:プラグイン（desktop.js）
jQuery.noConflict();

(function($, PLUGIN_ID) {
  // 略
    kintone.plugin.app.setConfig({message: $message.val()}, function() {
      alert('The plug-in settings have been saved. Please update the app!');
      window.location.href = '../../flow?app=' + kintone.app.getId();
    });
  // 略
})(jQuery, kintone.$PLUGIN_ID);
```

setConfigの引数１つ目は、プラグインに保存したい設定の内容です。
オブジェクト形式指定します。

```javascript:configの例
{ "key1": "value1", "key2": "value2" }
```

オブジェクトのプロパティ名（key1、key2）が、設定の項目名として扱われます。
これが、manifest.jsonの ``required_params`` （必須項目を指定するパラメータ）で指定していた項目名です。

サンプルプラグインでは次のようになっています。

```javascript:js/config.js
{message: $message.val()}
```

プラグインの設定値はオブジェクト形式なので、「プロパティ名(key）」と「値」が１対１でしか保存できません。
設定を配列にして保存するとか、階層をつけるということができない！
プラグインにたくさんの設定項目を持たせるときは、どのような構造としてプラグインの設定に保存するかしっかり考える必要があります。

### ポイント３：プラグイン設定保存後の動き

プラグインの設定画面で設定を保存したあとは、アプリの設定を保存しないとアプリにプラグインの設定は適用されません。
このため、サンプルプラグインでは設定保存後に "Please update the app!"　とアプリの保存を促すメッセージを表示し、アプリの設定画面に遷移しています。

```javascript:js/config.js
kintone.plugin.app.setConfig({message: $message.val()}, function() {
  alert('The plug-in settings have been saved. Please update the app!');
  window.location.href = '../../flow?app=' + kintone.app.getId();
});
```

この動きは必須ではありませんが、ユーザーの使いやすさを考慮すると「あったら便利」な機能です。

### ポイント４：プラグインの設定情報を取得する

プラグインの設定画面を表示するとき、**以前保存した内容を設定画面に表示する必要があります。**
何もせずに設定画面を描画すると、設定画面は何も入力されていない状態で表示されてしまうのです。

プラグインの設定情報を取得するために使うのが、[kintone.plugin.app.getConfig()](https://developer.cybozu.io/hc/ja/articles/203661160#step1) です。

```javascript
kintone.plugin.app.getConfig(pluginId);
```

引数の``pluginId``が、先ほどの即時関数の説明で出てきた``kintone.$PLUGIN_ID``で取得できる値です。こんな感じで使います。

```javascript:例
(function(PLUGIN_ID) {
  // プラグインの設定を取得
  var config = kintone.plugin.app.getConfig(PLUGIN_ID);

})(kintone.$PLUGIN_ID);
```

サンプルプラグインでは以下のように書かれています。

```javascript:js/config.js（８〜１３行目）
  var $message = $('.js-text-message'); // 入力フィールドの要素を取得
  var config = kintone.plugin.app.getConfig(PLUGIN_ID); // プラグインの設定情報を取得

  if (config.message) {
    $message.val(config.message); // 入力フィールドにプラグインの設定情報をセット
  }
```

プラグインの設定情報はオブジェクト形式で保存します。
このサンプルプラグインでは、``{message: "値"}``と保存していましたね。（config.jsの16行目）
設定を取り出すときに``config.message``と書いているのはそのためです。

### ポイント５：設定をキャンセルしたときの動き

設定をキャンセルしたら、ひとつ前の画面に戻りたいですよね。
サンプルプラグインでは以下のように書かれています。

```javascript:js/config.js（21〜23行目）
  $cancelButton.on('click', function() {
    window.location.href = '../../' + kintone.app.getId() + '/plugin/';
  });
```

設定をキャンセルしたときの動きも忘れずに書きましょう！


# プラグイン設定画面作成のために、知っておくと便利なライブラリ
- アプリの設定情報を簡単に取得　
    - [kintone-config-helper](https://developer.cybozu.io/hc/ja/articles/360023979211)　プラグインって設定画面でフィールド選ばせたい時あるよね。**絶対使って。詳しくは解説記事を読んでください。**
- kintone ライクな見た目にする
    - [51-modern-default.css](https://developer.cybozu.io/hc/ja/articles/203302214)
        - スタイルシートのみ（この記事でも解説したファイル）
    - [kintone UI Component](https://developer.cybozu.io/hc/ja/articles/900005544623)
        - 見た目を整えるだけでなく、JSも簡単に書けるので便利
        - ただし、カスタマイズとの競合に注意が必要
        <br>【参考】：https://qiita.com/juri_don/items/dd53fa86c1d21616a218

# 次回（以降）予告

- kintoneカスタマイズをプラグインに作り替えるポイントは？
    - kintoneカスタマイズとプラグインの書き方ってどこが違うの？
- プラグインの秘密鍵ってなに？なくすとどうなるの？
- プラグインのファイル名変えたら自動パッケージング＆アップロードできない？
- プラグインたくさん作りはじめたらディスク容量ひっ迫されてきた…
    - node_modules フォルダの容量が大きすぎて辛い。どうしたら？

まだまだ続くよ〜！