kintone javascriptテンプレートで最初の一歩を！

# はじめに
この記事は**「[kintone Advent Calendar 2020](https://qiita.com/advent-calendar/2020/kintone)」**の23日目の記事です！

kintoneでのカスタマイズと言えば、ノーコードやローコードと呼ばれるサービスを使ったり、各種プラグイン等を使ったりするというのが、最近ではスタンダードになってきた感はありますが、SIerの新入社員研修や大学や専門学校でプログラミングを教えている身としては、ぜひ自らコードを書いてほしいと思ったりする訳です。

コツさえ掴めば、安全かつ、学習コストをあまりかけずに、kintoneのjavascriptカスタマイズを行う事ができます。

本記事が、そういった方の一助になれば嬉しいです！


# プログラミング学習のコツ
私は、プログラミングの未学者や初学者を500人以上は教えてきていますが、その中でいつも次の事を伝えています。

* **「エラーの無い状態から始めましょう。」**
* **「ちょっとずつビルドアップしましょう。」**
* **「エラーの無い状態を維持しましょう。」**
* **「すぐに修正できるなら、間違ったコードではない」**

これはエラーが出た時に、「ここが間違っている！」という事が即座に分かるようにし続けるという事が大事なんですね。だからこそ、**まず最初にエラーが起きていない状態から始める**という事が肝要なのです。


# とはいえ、何から始めたらええねん！
というアナタのためにテンプレートとして使えるファイルをダウンロードできるように準備いたしましたので、お使いくださいませ！ダウンロードは**[コチラ](https://github.com/AISIC-DL/downloads/blob/master/js/template.js)**からどうぞ！
このファイルを「アプリの設定＞JavaScript / CSSでカスタマイズ」内のPC用のJavaScriptファイルとスマートフォン用のJavaScriptファイルの箇所にアップしたいただければと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319512/cb0e565a-62ed-c910-67a6-4e18fe458e93.png)

<details><summary>テンプレートjsファイル(tenplate.js)</summary><div>

```javascript
//=============================================================================
//【ファイル名】
//    template.js
//【アプリ名】
//    サンプルアプリ
//-----------------------------------------------------------------------------
//  Copyright (c) 2020 AISIC.Inc
//=============================================================================
'use strict';

// =============================================
// イベントモード
// =============================================
const EVENT_HANDLER_MODE = getEventHandlerMode();

(()=>{
    // =============================================
    // 定数
    // =============================================

    // =============================================
    // 共通関数
    // =============================================
    // ---------------------------------------------
    // 共通入力画面制御
    // ---------------------------------------------
    const setCommonInputCtrl = record => {
        // record.XXXXX.disabled = true;
        
    };  // setCommonInputCtrl

    // ---------------------------------------------
    // validation
    // ---------------------------------------------
    const validation = event => {
        
        const record = event.record;
        
        let errorFlg = false;
        
        let errorMsg = '';

        //     if (record.XXXXX.value) {
        //         record.XXXXX.error = '入力しないでください。';
        //         errorFlg = true;
        //     }
        // }

        if (errorFlg === true) {
            event.error = '入力内容に不備があります。';
        }
    };  // validation


    // =============================================
    // ADD EVENT HANDLER
    // =============================================
    // ---------------------------------------------
    // EVENT:create.show
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.create.show'
    ], async event => {
        const record = event.record;
        setCommonInputCtrl(record);
    
        return event;
    }); // create.show

    // ---------------------------------------------
    // EVENT:create.submit
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.create.submit'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // create.submit

    // ---------------------------------------------
    // EVENT:create.submit.success
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.create.submit.success'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // create.submit.success

    // // ---------------------------------------------
    // // [Promise非対応]
    // // EVENT:create.change.<field_code>
    // // ---------------------------------------------
    // kintone.events.on([
    //     EVENT_HANDLER_MODE + 'app.record.create.change.<field_code>'
    // ], event => {
    //     const record = event.record;
    
    //     return event;
    // }); // create.change.<field_code>

    // ---------------------------------------------
    // EVENT:edit.show
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.edit.show', 'app.record.index.edit.show'
    ], async event => {
        const record = event.record;
        setCommonInputCtrl(record);

        return event;
    }); // edit.show

    // ---------------------------------------------
    // EVENT:edit.submit
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.edit.submit', 'app.record.index.edit.submit'
    ], async event => {
        const record = event.record;
  
        return event;
    }); // edit.submit

    // ---------------------------------------------
    // EVENT:edit.submit.success
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.edit.submit.success', 'app.record.index.edit.submit.success'
    ], async event => {
        const record = event.record;
    
        return event;
    });

    // // ---------------------------------------------
    // // [Promise非対応]
    // // EVENT:edit.change.<field_code>
    // // ---------------------------------------------
    // kintone.events.on([
    //     EVENT_HANDLER_MODE + 'app.record.edit.change.<field_code>', 'app.record.index.edit.change.<field_code>'
    // ], event => {
    //     const record = event.record;
    
    //     return event;
    // }); // edit.change.<field_code>

    // ---------------------------------------------
    // EVENT:detail.show
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.detail.show'
    ], async event => {
        const record = event.record;
       
        return event;
    }); // detail.show

    // ---------------------------------------------
    // EVENT:delete.submit
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.detail.delete.submit', 'app.record.index.delete.submit'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // delete.submit

    // ---------------------------------------------
    // EVENT:process.proceed
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.detail.process.proceed'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // process.proceed

    // ---------------------------------------------
    // EVENT:index.show
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.index.show'
    ], async event => {
        const records = event.records;

        return event;
    }); // index.show

    // ---------------------------------------------
    // EVENT:print.show
    // ---------------------------------------------
    kintone.events.on([
        'app.record.print.show'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // print.show

    // ---------------------------------------------
    // EVENT:report.show
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'app.record.report.show'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // report.show

    // ---------------------------------------------
    // EVENT:portal.show
    // ---------------------------------------------
    kintone.events.on([
        EVENT_HANDLER_MODE + 'portal.show'
    ], async event => {
        const record = event.record;
    
        return event;
    }); // portal.show
})();

// =============================================
// MOBILEモード判定
// =============================================
function getEventHandlerMode() {
    let ret = '';
    if (kintone.mobile.app.getId() != null || kintone.mobile.portal.getContentSpaceElement() != null) {
        ret = 'mobile.';
    }
    return ret;
}; // end getEventHandlerMode
```
</div></details>


# コードの内容を少しだけ解説
### イベントモード
```javascript
// =============================================
// イベントモード
// =============================================
const EVENT_HANDLER_MODE = getEventHandlerMode();
```
プログラムの管理上、PC用とスマートフォン用とで同じファイルにしておきたいのだけども、PC用とスマートフォン用とでは**イベントタイプ**が異なり、概ねPC用のイベントタイプの先頭に**「mobile.」**という文字が付与された感じになっています。なので、kintoneを表示しているデバイスに応じたイベントタイプとするための文字列を生成します。
【参考】[kintone JavaScript API（イベント）一覧](https://developer.cybozu.io/hc/ja/articles/360000361686)

### 16行目と226行目
```javascript
(()=>{
   .
   .
   .
})();
```
画面の読み込みが完了したら```{ }```の間の処理を実行しますよ という意味。


### 共通入力画面制御
```javascript
// ---------------------------------------------
// 共通入力画面制御
// ---------------------------------------------
const setCommonInputCtrl = record => {
    // record.XXXXX.disabled = true;
};  // setCommonInputCtrl
```
「app.record.create.show」「mobile.app.record.create.show」「app.record.edit.show」「mobile.app.record.edit.show」「app.record.index.edit.show」のイベント内でcallされる関数。
いわゆる入力画面表示時に共通して実行したい処理をまとめておくために利用。弊社では、各フィールドを入力不可にする場合などに、使用することが多いですね。


### validation
```javascript
// ---------------------------------------------
// validation
// ---------------------------------------------
const validation = event => {
    const record = event.record;
    let errorFlg = false;
    let errorMsg = '';

    //     if (record.XXXXX.value) {
    //         record.XXXXX.error = '入力しないでください。';
    //         errorFlg = true;
    //     }
    // }

    if (errorFlg === true) {
        event.error = '入力内容に不備があります。';
    }
};  // validation
```
「app.record.create.submit」「mobile.app.record.create.submit」「app.record.edit.submit」「mobile.app.record.edit.submit」「app.record.index.edit.submit」のイベント内でcallされる関数。
いわゆる保存前時に共通して実行したい入力チェック処理をまとめておくために利用。個別のフィールドにエラー表示させると同時に画面上部にもエラーを表示することもできます。
![2020-12-22_01h59_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319512/9a307315-b2d5-30ba-049b-00aecbd0e02a.png)



# さいごに
kintoneのjavascript学習の王道と言えば、**[developer network](https://developer.cybozu.io/hc/ja)** ですよね！**[リファレンス](https://developer.cybozu.io/hc/ja/articles/360028177472)**もあるし、ちゃんと聞けばちゃんと答えてくれる人も多いですし(笑)

当たり前ではあるのですが、自分がやりたい事と100%同じことをやりたい人はいないし、kintoneアプリの目的が違うし、フィールドコードも違うのだから、developer networkやネット上のサンプルコードをコピペしたところで、正しく動きません。もし動いたとしたら、それはキセキに近い出来事です(苦笑)

大事な事なので、もう一度言いますが、**「サンプルコードのコピペだけでは動きません！」**

自分でコードを書くスキルを持つことは、自分のやりたいことを自分の手で作り上げることに繋がります。これは、自分のやりたいことを100%実現するという事に他なりません。

今回、改めて紹介させていただいたjavascriptのファイルが、kintoneでのjavascriptカスタマイズを始めてみようと思っている方にとっての最初の一歩になってくれたら幸いです！


ちなみに、kintoneでの開発者向けjacascriptカスタマイズ学習に特化した**[TENJIKU](https://clouduniversity.jp/kintone/kintone-tenjiku/)**の講師もしておりますので、この分野を身に付けたいという方は是非お声掛けいただければと＾＾


# おしらせ１
kintoneでjavascriptカスタマイズをするときに、開発をサポートするような**[kintone_tools](https://github.com/j-kume/kintone_tools)**もチマチマとバージョンアップしております。
皆さんからのアイデアも欲しいですし、一緒に開発を進めていただける方も絶賛募集中ですので、ぜひご協力いただけると嬉しいです！



# おしらせ２
弊社サービスとして、**[レスキュトーン](https://www.rescutone.com/)**、**[リノベトーン](https://www.renovatone.com/)**というkintone関連サービスをしています。
kintoneに絡んだご相談など、お気軽にお問い合わせいただければと思います！
[<img width="300" alt="2020-11-11_11h00_00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319512/3dd897b5-4e24-af0e-23fa-fee0cc2c1b09.png">](https://www.rescutone.com/) [<img width="300" alt="2020-11-11_11h00_13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319512/c76df839-ac18-95b5-e57f-baeccf911e27.png">](https://www.renovatone.com/)