見出し画像

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

やりたいこと

kintone標準機能の日時フィールドは日付と時刻の入力支援ツール(Picker)が使える入力部品ですが、時刻部分の入力範囲が00:00~23:59のフルタイムで時刻選択も30分間隔であり、この設定を変更することはできません。
参照:Kintoneヘルプ/日時
しかし、時刻部分の表示範囲を会社の営業時間内に制限したり、時刻選択の間隔をもっと細かくしたいという現場ニーズはあると思います。

kintone UI Component v1を利用すれば、日時フィールド時刻の開始~終了範囲を変更したり、時刻選択の間隔を自由指定できる日時フィールドを作成することができます。
今回は、時刻の開始~終了範囲を09:00~18:00に制限して、時刻選択を15分間隔にする日時フィールドのカスタマイズ例をご紹介します。

デモ画面 

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

KUC版DateTimePickerデモ画面

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

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


アプリの設定方法

(1)アプリの準備

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

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

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

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

/* KUC版の日時フィールドを作成 */
(() => {
  'use strict';

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

  // 日時のフォーマット
  function formatDateTime(DateTime) {
      const year  = DateTime.getFullYear();
      const month = String(DateTime.getMonth() + 1).padStart(2, '0');
      const day   = String(DateTime.getDate()).padStart(2, '0');
      const hour  = String(DateTime.getHours()).padStart(2, '0');
      const min   = String(DateTime.getMinutes()).padStart(2, '0');
      const fomat_date = `${year}-${month}-${day}`;
      const fomat_time = `${hour}:${min}`;
      return [fomat_date, fomat_time]; 
  };

  // 日時パラメータの初期化
  let Value_dateTime = "";
  if (SET_nowTime == 1) {
      let [dateValue, timeValue] = formatDateTime(new Date());
      Value_dateTime = `${dateValue}T${timeValue}`;
      // 日時パラメータの時刻範囲のチェック
      if (timeValue < SET_minTime) { Value_dateTime = `${dateValue}T${SET_minTime}` }; // 開始時間Check
      if (timeValue > SET_maxTime) { Value_dateTime = `${dateValue}T${SET_maxTime}` }; // 修了時間Check
  }

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

  // KUC版DateTimePickerを作成し、スペース要素に追加する関数
  function createDateTimePicker(spaceElement) {
    const dateTimePicker = new Kuc.DateTimePicker({
      label: 'KUC版日時',
      requiredIcon: true,
      language: 'auto',
      hour12: false,
      value: Value_dateTime,
      min: SET_minTime,
      max: SET_maxTime,
      timeStep: SET_stepTime,
      className: 'options-class',
      id: 'options-id',
      visible: true,
      disabled: false,
    });
    // KUC版dateTimePickerの値変更イベント
    dateTimePicker.addEventListener('change', (event) => {
      updateField(event.target.value);
    });
    // KUC版dateTimePickerの表示
    spaceElement.appendChild(dateTimePicker); 
  }

  // Kintoneイベント設定
  kintone.events.on(['app.record.create.show'], (event) => {
    const spaceElement = kintone.app.record.getSpaceElement(KUC_SPACE_ID);
    if (spaceElement) {
      spaceElement.innerHTML = '';
      createDateTimePicker(spaceElement);    // KUC版日時FIELDの表示
      kintone.app.record.setFieldShown(FIELD_DATE_TIME, false); // 標準版日時FIELDを非表示にする
    } else {
      console.error('指定されたスペース要素が見つかりません。');
    }
    return event;
  });
})();

上記サンプルコードでは、レコード新規登録画面でKUC版DateTimePickerを動作させています。レコード編集画面でKUC版DateTimePickerを動かす処理は未実装です(標準日時フィールドで編集できます)。
興味のある方はご自身で工夫して必要な機能を追加してみて下さい。

レコード編集画面では、日時フィールドの値(UTC/協定世界時)を日時のオブジェクトに変換してJST/日本標準時間で日付パラメータに組み立て直す等の少々面倒な操作が必要です。しかし頑張って実装しても出来ることは、日時フィールドの時刻部分の入力範囲制限と時刻リストの間隔を変更するだけなので、個人的には「苦労の割に出来ることが少ない」と感じましたので、編集時は標準日時フィールドのままで良いのでは?と思いました。

スタイルのCSSカスタムコード

Kintoneコーディングガイドラインでは、各要素に付与されている id や class 属性の値は、kintoneのアップデートで将来予告なく変更されることがあるので、CSSコードによる id や class 属性の値操作は非推奨です。
しかしkintone UI Componentの各コンポーネントは、専用のCSSプロパティを持っています。
KUC版DateTimePickerもCSSコードの専用プロパティを持っています。
以下にフィールドの文字色(緑)や文字の大きさ等を指定するCSSコードの記載例を掲載しておきます。
JavascriptコードのKUC版DateTimePickerのプロパティ” id: 'options-id',”とCSSコードの"#options-id"を合わせて利用して下さい。

/* KUC版DateTimePicker
   CSSプロパティの指定サンプル */
#options-id {
  /* 日時の文字色指定 */
  --kuc-date-time-picker-input-color: green;
  /* 日時の文字フォントサイズの指定 */
  --kuc-date-time-picker-input-font-size: 24px;
  /* 日付フィールド部分の横幅の指定 */
  --kuc-date-time-picker-date-input-width: 180px;
  /* 時刻フィールド部分の横幅の指定 */
  --kuc-date-time-picker-time-input-width: 120px;
}

(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でしたが、日時の場合は入力値保存用に日時型のフィールドを準備して、日時フィールド型のフォーマットで値を渡す必要があります。
もし文字列1行型フィールドで保存すると、編集モードで文字列入力になるので日付と時間の入力支援機能(DateTimePicker)が表示されません。
検索や集計処理でも日時アイテムとして条件比較ができなくなります。

また、自動取得した現在日時の時刻が初期設定の時刻開始~終了の範囲外の値の場合、そのままプロパティ値(Value)にしてKUCコンポーネントを作成すると、コードエラー"Uncaught (in promise) Error: Time is out of valid range."が発生するので、そのハンドリングも必要です。
この部分はTimePickerのカスタマイズの時と同じ注意が必要でした。
kintone UI Component側で作成時にも警告メッセージを画面表示する様に仕様変更してくれることを期待したいと思います!)

今回も、最後まで読んで頂いてありがとうございました。

★以下の有料記事の内容は、KUC版DateTimePickerをレコード編集画面でも動作する様に挑戦した個人的な記録と日時フィールドで勉強した覚書です。
 色々と試行錯誤した恥ずかしい記録なので有料記事エリアで隠してます。
(販売目的ではありませんので、誤って購入しないでくださいw)


ここから先は

5,761字 / 1画像

¥ 1,000

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