クリスマスなのでケーキをえらびます

# はじめに
[kintone Advent Calendar 2019 Part2](https://qiita.com/advent-calendar/2019/kintone2) 16日目の記事です。ｲｼｲｹﾝﾀﾛｳです。刷毛をつくってる会社にいます。
[![main_image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/564c7de8-6fc7-61c7-a97f-f8d0a7c9943d.jpeg)](https://www.maru-t.co.jp/painting_brush/)

# 自己紹介です
- 刷毛をつくっている会社の兼業情シスです。kintone認定資格は3つとも取得済です
- その他にITストラテジストや[情報処理安全確保支援士](https://riss.ipa.go.jp/r?r=010775)などの国家資格をいくつか取得しています
- kintoneのカスタマイズは社内向けのみで、プラグインは作ってません（作れません）
- [12/10の金春さんの記事](https://blog.r3it.com/scary-customization-8e5a0ac2c7c3)を拝読し、かなりビビッてます
- [JavaScriptの便利な書き方](https://developer.cybozu.io/hc/ja/articles/360031341211-JavaScript%E3%81%AE%E4%BE%BF%E5%88%A9%E3%81%AA%E6%9B%B8%E3%81%8D%E6%96%B9)を鋭意学習中です

![アソシエイト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/761a3907-f9f7-4da5-c5e9-9ae9e9d90e04.png)　![アプリデザイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/3fa2bf0c-e0f9-f8ea-a9fb-88611caa545b.png)　![カスタマイズ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/476db7b8-509f-a484-7913-2dd61afa63f2.png)

# この記事の対象となる読者の方
- kintoneのカスタマイズを「全く触ったことないけど興味はある方」から、「少しだけ触ったことある方」くらいまでです。
- 具体的には[Hiroyuki Maeda](https://twitter.com/hiroyukimaeda_3)さんと[コンノ](https://twitter.com/konnosdg)さんのお2人が頭に浮かんでました。
- RESTAPIは使ってるけど、Promiseは使ってません。
- ただサブテーブルにユーザー選択と、初見殺しを2つ重ねてしまいました。value地獄ですがちょっとだけ頑張ってみてくださいスミマセン。
- 疑問点や懸念事項はtwitterで絡んでください。twitterも同じ @kentaro1sh11 です。

# 運用の流れ

1. アプリ管理者が予め選択肢として、レコードにケーキの種類を登録しておきます。
2. ケーキをたべたいひとは、詳細画面に表示されたラジオボタンでケーキを選び、ボタンで確定します。
3. 自動的に再読み込みされ、自分が選んだケーキの横に名前が掲載されます。
4. 全員の意見が出そろったらアプリ管理者がケーキを買いに行きます。

![ケーキえらび.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/bc447859-5c27-dd93-45cc-959624e41309.png)

# 事前準備

kintone UI Component を利用します。ご存じない方は、以下のリンクを参考に、[こちら](https://github.com/kintone/kintone-ui-component/tree/master/dist) から js と css をダウンロードしておいてください。
【参考】[「kintone UI Component」を使って簡単にkintoneライクなUIを設置する](https://developer.cybozu.io/hc/ja/articles/360000511023--kintone-UI-Component-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E7%B0%A1%E5%8D%98%E3%81%ABkintone%E3%83%A9%E3%82%A4%E3%82%AF%E3%81%AAUI%E3%82%92%E8%A8%AD%E7%BD%AE%E3%81%99%E3%82%8B)

# フォーム設定
![アプリ設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/4b2609db-0c59-436b-8b3e-381530d6418a.png)

| フィールド名                     |フィールドタイプ    |フィールドコード    |
|:--------------------------------|:------------------|:------------------|
| ケーキをたべるひ                 | 日付              |cakeDate           |
| (ラジオボタン用スペース)          | スペース           |radioSpace        |
| (ボタン用スペース)               |スペース           | btnSpace           |
| (ケーキ一覧テーブル)             | テーブル          | cakeTable          |
| (テーブル項目)<br>ケーキのなまえ  |文字列（１行）     | cakeName           |
| (テーブル項目)<br>ケーキのしゃしん|添付ファイル       | cakePhoto          |
| (テーブル項目)<br>たべたいひと    |ユーザー選択       | cakeUserName       |



# レコード新規作成

日付と、ラジオボタンの選択肢としてのケーキ名称、およびユーザーがケーキ選択時の参考となるようにケーキの画像を登録します。（画像はいらすとやさんですいつもありがとうございます）
![レコード作成画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/facb0531-b9c7-5476-86ec-95907d318990.png)

レコードを保存すると自動的にラジオボタンと確定ボタンが表示されます。
![ケーキえらび.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/bc447859-5c27-dd93-45cc-959624e41309.png)

# javascript

コピーして名前を付けて保存し（画像ではselectCake.js）、kintone UI Component とともにアップロードしてください。
![jsファイルアップロード画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/6bfaacc2-cd63-9d87-95ff-af4b2578c28f.png)


```javascript

(function() {
    "use strict";

    // 詳細画面が表示されたとき
    kintone.events.on('app.record.detail.show', function(event) {
        const record = event.record;

        // ラジオボタン用スペースの取得と、divタグ作成
        const radioSpace = kintone.app.record.getSpaceElement('radioSpace');
        const divRadioSpace = document.createElement('div');
        divRadioSpace.id = 'divRadioSpace';

        // ラジオボタン作成用配列に、テーブルからケーキ名を取得して、ひとつずつ格納
        const itemsCake = [];
        for(let i = 0; i < record.cakeTable.value.length; i++){
            const cakeName = record.cakeTable.value[i].value.cakeName.value;
            itemsCake[i] = {
                'label': cakeName, 
                'value': cakeName
            };
        }

        // ラジオボタンを作成し1つ目の選択肢を選択済にして、スペースに配置
        const radioBtn = new kintoneUIComponent.RadioButton({
            name: 'radioCake',
            items: itemsCake,
            value: record.cakeTable.value[0].value.cakeName.value
        });
        divRadioSpace.appendChild(radioBtn.render());
        radioSpace.appendChild(divRadioSpace);


        // ボタン用スペースの取得と、div作成
        const btnSpace = kintone.app.record.getSpaceElement('btnSpace');
        const divBtnSpace = document.createElement('div');
        divBtnSpace.id = 'divBtnSpace';

        // ボタンを作成してスペースに配置
        const btnCake = new kintoneUIComponent.Button({
            text: 'たべたいケーキをきめる',
            type: 'submit'
        });
        divBtnSpace.appendChild(btnCake.render());
        btnSpace.appendChild(divBtnSpace);


        // 確定ボタンをクリックしたとき
        btnCake.on('click', function(){
        
            // レコード登録内容の取得
            const record = kintone.app.record.get().record;
            // ラジオボタンの取得
            const selectCake = document.getElementsByName('radioCake');
            // テーブル上書き用配列
            const tmpCakeTableValue = [];

            // ラジオボタンで選ばれたケーキの行のユーザー選択に、ログインユーザー情報を登録
            for(let i = 0; i < selectCake.length; i++){
                if(selectCake[i].checked === true){
                    //ユーザー選択を更新した行を配列に格納
                    record.cakeTable.value[i].value.cakeUserName.value.push({
                        'code': kintone.getLoginUser().code, 
                        'name': kintone.getLoginUser().name
                    });
                }
                // 選ばれてないケーキの行はそのまま配列に格納
                tmpCakeTableValue.push({
                    'id': record.cakeTable.value[i].id, 
                    'value': record.cakeTable.value[i].value
                });
            }

            // レコード更新api用のパラメータ作成
            const body = {
                'app': kintone.app.getId(),
                'id': kintone.app.record.getId(),
                'record': {
                    'cakeTable': {
                        'value': tmpCakeTableValue
                    }
                }
            };
            
            // レコードの更新と画面のリロード
            kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body, function(resp){
                console.log(resp);
                location.reload();
            },function(error){
                console.log(error);
            });

        });// ここまで確定ボタンをクリックしたとき

    });// ここまで詳細画面が表示されたとき

})();

```

# かんたんな解説
1. レコード詳細画面表示時に、テーブルからケーキ名称を読み込んだラジオボタンと、確定ボタンを動的に作成します。
2. 確定ボタンクリック時にログインユーザーを選ばれたケーキのユーザー選択に加えます。
3. 画面をリロードさせることで、選んだケーキの横に名前が表示されます。

# 完成！
![完成！.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/49cad5c5-1adc-1f1c-4141-11b2ed48fbb1.png)
おとうさんは生クリームが苦手なのでチーズケーキを選びます

# 気づいたこととか
- テーブルが0行だとエラーが出ると思って処理を書いたんですがテーブル仕様上0行はあり得ないと気づいて消しました
- テーブルにケーキ単価フィールドを加えてもらうと合計金額を計算できて買いに行くとき便利ですきっと
- 複数人が同時に確定ボタンをクリックすると非同期処理の後出し勝ちになります（たぶん）
- forループの中のconstは再宣言にならない？あまり良い使い方ではないのかしら？
- モバイルのことは何も考えてなかったのでまた今度考えます
- いまさらですがいらすとやさんに[ブッシュドノエル](https://www.irasutoya.com/2012/12/blog-post_622.html)あったんですね・・・
- ケーキを間違えて選んだときはレコード編集画面で修正するしかないとたったいま判明したので、決して間違えてはいけません

# おわりに
例によって @Shokun1108 にそそのかされました。
ケーキ以外でもアンケート風なこととかなんとなくできそうです。良かったらお試しください。
でもスミマセンなんかあっても責任取れませんゴメンね（ビビッてます）

あと、塗装用ローラーもつくってます。
[![main_image (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105085/d20f1b7b-355a-1524-829f-71fcd21bdfed.jpeg)](https://www.maru-t.co.jp/painting_roller/)