見出し画像

時刻フィールドの開始~終了範囲の変更&15分間隔で時刻選択を可能にする

やりたいこと

kintone標準機能の時刻フィールドは入力範囲が00:00~23:59のフルタイムで時刻選択も30分間隔であり、この設定を変更することはできません。
参照:Kintoneヘルプ/時刻
しかし、時刻の表示範囲を会社の営業時間内に制限したり、時刻選択の間隔をもっと細かくしたいという現場ニーズはあると思います。
kintone UI Component v1を利用すれば、時刻の開始~終了範囲を変更したり、時刻選択の間隔を自由指定できる時刻フィールドを作成できます。
今回は、時刻の開始~終了範囲を09:00~18:00に制限して、時刻選択を15分間隔にする時刻フィールドのカスタマイズ例をご紹介します。

デモ画面 

デモ画面では、比較のために標準機能の時刻フィールドとカスタマイズ版の時刻フィールド(以降「KUC版TimePicker」と呼びます)を並べて表示しています。KUC版TimePickerでは、選択範囲を09:00~18:00の間で15分間隔で表示できていることが分かると思います。
選択範囲外の時刻(例えば、00:30)をキーから直接入力すると「時刻が有効な範囲外です」と警告メッセージが表示される仕様です。
※範囲外の警告メッセーは、時刻を半角入力した場合だけ表示されます。
 全角モードで半角変換しても警告メッセージは表示されません。

KUC版TimePickerのデモ画面

なお、標準機能の時刻フィールドには新規レコード作成時に現在時刻を初期値でセットする機能がありますが、KUC版TimePickerには現在時刻を取得する機能はありませんので、Javascriptカスタマイズで実装しています。

KUC版TimePickerの詳しい仕様は、以下のサイトを参照して下さい。


アプリの設定方法

(1)アプリの準備

KUC版TimePickerを表示するアプリを準備します。
必要なフィールド名(フィールドコード)は以下の通りです。
フィールド名は自由ですが()内のフィールドコードは、Javascriptの設定と合わせる必要が有ります。
<KUC版TimePickerを設置するアプリ>
・時刻型   :フィールド名:KUC版時刻(時刻_TIME
・スペース  :要素ID:Space_Time

(2)KUC版TimePicker設置のJavascriptコード

 初期設定でKUC版TimePickerを表示する[スペースID]、時刻の値を保存する[フィールドコード]、時刻入力範囲の[開始時刻(SET_minTime)」と[終了時刻(SET_maxTime)]、[時刻間隔(SET_stepTime)]を設定します。
SET_nowTime = 0にすると時刻フィールドは空白で表示されます。
SET_nowTime = 1にすると時刻フィールドに現在時刻がセットされます。

【現在時刻の自動取得の注意事項】
自動取得した現在時刻(Time_Value)が初期設定の開始~終了時刻の範囲外だとKUCオブジェクト作成処理でコードエラーが発生します。
KUC版TimePickerの作成関数の先頭で警告メッセージを出す等のエラーハンドリングをする方が親切設計なのですが、面倒なことがコードが冗長になるのが嫌なので、現在時刻<開始値の場合はSET_minTime、現在時刻>終了値の場合はSET_maxTimeの値に上書きしています。
例)19:15→18:00(終了値)に強制的に上書きしています。

/* KUC版TimePickerを作成 */
(() => {
  'use strict';

  // 初期設定
  const KUC_SPACE_ID = 'Space_Time'; // KUC版TimePickerを配置するスペース要素IDコード
  const FIELD_CODE   = '時刻_TIME';  // 時刻フィールドコード
  const SET_minTime  = '09:00';      // 時刻入力範囲の開始値
  const SET_maxTime  = '18:00';      // 時刻入力範囲の終了値
 const SET_stepTime = 15;           // 時刻リスト内の時刻間隔の設定
 const SET_nowTime =  1;            // 現在時刻をセット 0:しない/1:する
 //<------- 初期設定ここまで -------->

  // 現在時刻取得関数
  const getCurrentDateTime = () => {
      const now = new Date();
      const hour = now.getHours().toString().padStart(2, '0');
      const min = now.getMinutes().toString().padStart(2, '0');
      return `${hour}:${min}`;
  };

  // 時刻用の変数を宣言(SET_nowTimeの値で初期値を変える)
  let Time_Value = (SET_nowTime == 1) ? getCurrentDateTime() : "";

  // フィールド更新関数
  function updateField(newValue) {
    const record = kintone.app.record.get();
    record.record[FIELD_CODE].value = newValue;
    kintone.app.record.set(record);
  }

  // KUC版TimePickerの作成
  function createTimePicker(spaceElement) {
  // Time_Valueの値が初期設定の開始~終了時刻範囲を超えている場合の処理
    if (Time_Value !== "") {
        if (Time_Value < SET_minTime) { Time_Value = SET_minTime; }
        if (Time_Value > SET_maxTime) { Time_Value = SET_maxTime; }
    }
    const timePicker = new Kuc.TimePicker({
      label: 'KUC版時刻',
      requiredIcon: true,
      language: 'auto',
      hour12: false,
      value: Time_Value,
      min: SET_minTime,
      max: SET_maxTime,
      timeStep: SET_stepTime,
      className: 'options-class',
      id: 'options-id',
      visible: true,
      disabled: false,
    });

    // KUC版TimePickerの値の変更イベント処理
    timePicker.addEventListener('change', (event) => {
      updateField(event.detail.value); // 時刻フィールドの更新
    });
    spaceElement.appendChild(timePicker); // KUC版時刻フィールドの表示
  }

  // kintoneのイベント設定
  kintone.events.on(['app.record.create.show', 'app.record.edit.show'], (event) => {
    const record = event.record;
    const spaceElement = kintone.app.record.getSpaceElement(KUC_SPACE_ID);

    // レコード編集画面での日時FIELD値の読み込み
    if (event.type === 'app.record.edit.show') {
        Time_Value = record[FIELD_CODE].value; // レコード値の取得
    }

    if (spaceElement) {
      spaceElement.innerHTML = '';
      createTimePicker(spaceElement);    // KUC版日時FIELDの表示
      kintone.app.record.setFieldShown(FIELD_CODE, false); // 標準版時刻FIELDを非表示にする
    } else {
      console.error('指定されたスペース要素が見つかりません。');
    }
    return event;
  });
})();

(3)アプリの設定>JavaScript / CSSでカスタマイズ

KUC版ボタン」を設置するアプリの、アプリの設定>JavaScript / CSSでカスタマイズの画面で、kintone UI ComponentのCDNをURL指定で追加し、次に初期設定済のJavascriptコードをアップロードして追加します。

最新版の kintone UI Component は、以下のCDNで利用できます。https://unpkg.com/kintone-ui-component/umd/kuc.min.js

https://kintone-ui-component.netlify.app/ja/docs/getting-started/quick-start/

最後に、アプリの更新を完了させれば、設定は完了です。
もしエラーで動作しない場合は、フィールドコードやスペース要素IDの設定が正しいか見直してください。

【注意事項】 2024/04/16加筆

kintone UI ComponentのCDN版は動作試験の目的でのみご利用ください。
本番環境で利用する際はUDM版が推奨です。
詳しくは、以下の記事を参照して下さい。


カスタマイズした感想

kintone UI Componentのフィールド型のコンポーネントは、Kintoneライクなフィールドを作成するだけなので、入力値保存用のフィールドを別途用意する必要があります。
これまでのドロップダウンリスト、ラジオボタン、チェックボックス等は、文字列1行型フィールドへの保存でOKでしたが、時刻の場合は入力値保存用に同じ型のフィールドを準備して、HH:MMのフォーマットで値を渡す必要があります。
そうしないと時刻として検索や集計ができなくなるからです。

さらに自動取得した現在時刻が、初期設定の時刻開始~終了の範囲外の値で、そのままプロパティ値(Value)にしてKUCコンポーネントを作成すると、コードエラー"Uncaught (in promise) Error: Time is out of valid range."が発生するので、そのハンドリング(手抜き)も必要でした。
  ↑
この仕様に思いっきりハマりました(泣)
さっきまで動いていたコードが急にエラーになり、原因が分からずに諦めて翌日の昼間に試すと何事もなく動くので「なんで??」状態でしたが、よく考えたら、自分で設定した終了時刻(18:00)を超えた時間帯に動作テストしていたのが原因だった!・・・というトホホな落ちでした。

デモ画面の様にキー入力で設定範囲外の時刻を入力すると画面に「時刻が有効な範囲外です」と警告メッセージが表示される仕様なのですが、KUCオブジェクトの作成時に設定範囲外の時刻を渡すとコードエラーになるのがハマりポイントでした(kintone UI Component側で作成時にも警告メッセージを画面表示する様に仕様変更してくれることを期待したいと思います!)

注意事項の追記

もし、職場にKintoneアソシエイト認定資格試験を受験予定のメンバーが居る場合は、KUC版TimePickerを装備したアプリは「カスタム仕様です」と事前説明するか、またはあえて「見せない」ことを推奨します。
アソシエイト試験の練習問題の中に時刻フィールドの仕様に関する設問があり、時刻フィールドの入力範囲や30分間隔の変更はできないのが「正解」なので、KUC版TimePickerを装備したアプリを見てしまうと、きっと混乱すると思いますw

次回は、KUC版日時フィールドのカスタマイズに挑戦したいと思います。
今回も、最後まで読んで頂いてありがとうございました。

よろしければサポートお願いします! いただいたサポートは、note記事制作の活動費に使わせていただきます!