ドロップダウンの値によって、別フィールドの値を変更・無効に設定する

目次

概要

こちらのサンプルは、「ドロップダウン」フィールドの選択によって、別のフィールドの値を変更したり、入力を無効にするカスタマイズです。

また、「自動採番」「期間チェック」「任意の場所に外部リンクを表示させる」などの、便利な機能を実現させるサンプルも含まれています。

完成形

デモ環境

cybozu developer network DemoSite (External link) のデモ環境で実際に動作を確認できます。
ログイン情報は cybozu developer networkデモ環境 で確認してください。

準備

適用手順

JavaScriptファイルの追加

  1. まずは、設定画面でカスタマイズに必要なライブラリを追加します。
    アプリの設定画面から「JavaScript / CSSによるカスタマイズ」を開き、「PC用のJavaScriptファイル」に、URL指定で次のライブラリを順番に指定します。
    Luxon:https://js.cybozu.com/luxon/3.7.1/luxon.min.js
    ライブラリの詳細は、 Cybozu CDN を参照してください。
  2. 指定したライブラリの下に、後述の「サンプルプログラム」を追加します。
    サンプルプログラム 部分のコードをエディターにコピーし、58行目のhttps://example.comを実際の路線検索サイトのURLに書き換えてください。
    ファイル名を「sample.js」、文字コードを「UTF-8」、BOMなしで保存します。
    ファイル名は任意ですが、ファイルの拡張子は「js」にしてください。

設定画面の完成イメージ

「JavaScript / CSSによるカスタマイズ」画面でそれぞれ設定した例を紹介します。

サンプルプログラム

サンプルプログラムでは、 Cybozu CDN の利用、JavaScriptのサンプルを紹介します。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
 * 旅費精算申請のプログラム
 * Copyright (c) 2025 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

(() => {
  'use strict';

  // 地域の条件に応じて日当を変更する。
  const changeArea = (event) => {
    const record = event.record;

    switch (record.地域.value) {
      case '首都圏':
        record.日当.value = '0';
        record.日当.disabled = true;
        break;
      case '海外':
        record.日当.value = '3000';
        record.日当.disabled = true;
        break;
      case 'その他':
        record.日当.disabled = false;
        break;
      default:
        record.日当.value = '1000';
        record.日当.disabled = true;
        break;
    }
  };

  // レコード追加、編集前、地域変更で処理を実行する
  const events = ['app.record.create.show', 'app.record.edit.show', 'app.record.index.edit.show',
    'app.record.edit.change.地域', 'app.record.create.change.地域', 'app.record.index.edit.change.地域'];
  kintone.events.on(events, (event) => {

    event.record.No.disabled = true;
    if (('app.record.create.show').indexOf(event.type) >= 0) {
      event.record.No.value = '';
    }

    // 地域変更による他のフィールド値変更
    changeArea(event);

    // 路線検索リンク表示
    const el = kintone.app.record.getSpaceElement('TravelSearch');
    // すでに設定されている子ノードがあったら削除する
    for (let i = el.childNodes.length - 1; i >= 0; i--) {
      el.removeChild(el.childNodes[i]);
    }

    const elTravel = document.createElement('a');
    elTravel.appendChild(document.createTextNode('路線検索サイト(外部サイト)'));
    // 路線検索サイトのリンクを指定します。
    elTravel.setAttribute('href', 'https://example.com');
    elTravel.setAttribute('target', '_blank');
    el.appendChild(elTravel);

    return event;
  });

  // 出発、帰着の値変更時のエラーチェックをする
  const eventCheck = ['app.record.create.change.出発', 'app.record.create.change.帰着',
    'app.record.edit.change.出発', 'app.record.edit.change.帰着',
    'app.record.index.edit.change.出発', 'app.record.index.edit.change.帰着'];
  kintone.events.on(eventCheck, (event) => {

    const record = event.record;
    const vlFrom = record.出発.value;
    const vlTo = record.帰着.value;
    record['出発'].error = null;
    record['帰着'].error = null;

    // 出発が空白で、帰着が空白でない場合
    if (!(vlFrom) && (vlTo)) {
      record.出発.error = '出発日を入力してください。';

    } else if ((vlFrom) && (vlTo)) {
      // 帰着が出発より前に設定されている場合
      if (vlFrom > vlTo) {
        record.帰着.error = '出発日よりあとに変更してください。';
      }
    }
    return event;

  });

  // レコード追加、編集の保存前に自動採番を作成する
  const eventSubmit = ['app.record.create.submit', 'app.record.edit.submit', 'app.record.index.edit.submit'];
  kintone.events.on(eventSubmit, async (event) => {

    // 保存前の画面上のレコード
    const record = event.record;
    // Luxon CDN利用時
    const DateTime = luxon.DateTime;
    const currentDate = DateTime.now();

    // 旅費、経費が出発や帰着の範囲内でない場合はエラーを表示する
    const vlFrom = record.出発.value;
    const vlTo = record.帰着.value;

    // 旅費
    for (let i = 0; i < record.旅費.value.length; i++) {
      const vlDate = record.旅費.value[i].value.旅費日付.value;

      if (!vlDate) {
        continue;
      }

      if ((vlDate < vlFrom) || (vlDate > vlTo)) {
        event.error = '旅費日付が申請期間の範囲外です。';
        record.旅費.value[i].value.旅費日付.error = '旅費日付が申請期間の範囲外です。';
        return event;
      }
    }

    // 経費
    for (let i = 0; i < record.経費.value.length; i++) {
      const vlDate = record.経費.value[i].value.経費日付.value;

      if (!vlDate) {
        continue;
      }

      if ((vlDate < vlFrom) || (vlDate > vlTo)) {
        event.error = '経費日付が申請期間の範囲外です。';
        record.経費.value[i].value.経費日付.error = '経費日付が申請期間の範囲外です。';
        return event;
      }
    }

    // Noが空白の場合に処理する。
    if (!record.No.value) {
      const appId = kintone.app.getId();
      const query = 'limit 1&fields[0]=$id';
      const appUrl = `${kintone.api.url('/k/v1/records', true)}?app=${appId}&query=${encodeURI(query)}`;
      let recNo = 1;
      try {
        const resp = await fetch(appUrl, {headers: {'X-Requested-With': 'XMLHttpRequest'}});
        if (!resp.ok) throw new Error(resp.statusText);
        const obj = await resp.json();
        if (obj.records[0] != null) {
          recNo = parseInt(obj.records[0].$id.value, 10) + 1;
        }
        // Luxonで自動採番を見積番号に設定する
        const autoEstNo = 'T' + currentDate.toFormat('yyLLdd') + '-' + recNo;
        alert(`番号 ${autoEstNo} を登録します`);
        event.record.No.value = autoEstNo;
      } catch (e) {
        event.error = `番号が取得できません。${e}`;
        return event;
      }
      return event;
    }

  });

  // レコード表示時の処理
  kintone.events.on('app.record.detail.show', (event) => {

    // 精算金額のスタイルを変更する
    const elTotal = kintone.app.record.getFieldElement('精算金額');
    elTotal.style.fontWeight = 'bold'; // 太字
    elTotal.style.fontSize = 'large';

    // 印刷ボタンの表示
    const elPrint = document.createElement('button');
    elPrint.style.height = '30px';
    elPrint.style.width = '50px';
    elPrint.style.borderRadius = '0.5em';
    elPrint.appendChild(document.createTextNode('印刷'));
    elPrint.addEventListener('click', () => {
      alert('印刷するボタンの例です。\n実際には印刷されません。');
    }, false);

    kintone.app.record.getHeaderMenuSpaceElement().appendChild(elPrint);
  });

})();

使用したAPI

information

このTipsは、2025年8月版kintoneで動作を確認しています。