開発情報・ナレッジ

投稿者: ShiningStar株式会社 2025年6月13日 (金)

マルチセレクトでその他を選択した時に入力欄の活性化・非活性化を切り替えるサンプルプログラム

本記事では、HTMLのチェックボックス群において、
「その他」の選択肢(特定のチェックボックス)が選ばれた際に、
関連するテキスト入力欄を動的に活性化・非活性化するJavaScriptの実装方法を紹介します。

この機能により、ユーザーが必要な場合にのみ追加情報の入力を求めることができ、
フォームのユーザビリティ向上に繋がります。

機能の全体像

この機能は、ユーザーがチェックボックス群の中から「その他」オプションを選択した際に、
付随するテキスト入力フィールドを操作可能(活性化)にし、
それ以外の選択肢を選んでいる場合や「その他」の選択を解除した際には
テキスト入力フィールドを操作不能(非活性化)にするものです。

具体的には、以下の要素と仕組みで実現されます。

  • HTML要素:
    • 複数の選択肢を表すチェックボックス群。(SPIRALで吐き出されるマルチセレクトフィールドのinput要素)
    • その中の一つで「その他」を意味する特定のチェックボックス。(特定のvalue属性を持つ)
    • 「その他」が選択された際に具体的な内容を入力するためのテキストフィールド。

  • CSS (任意):
    テキストフィールドが非活性状態であることを視覚的に示すためのスタイル。

  • JavaScript:
    • 「その他」チェックボックスの状態変化を監視します。
    • 状態が変わると、テキストフィールドのreadOnly属性やCSSクラスを切り替えることで、活性/非活性を制御します。
    • 初期表示時にも、テキストフィールドの状態を適切に設定します。

これにより、ユーザーが「その他」を選択した時だけ関連テキストフィールドが入力可能となり、
不要な入力や混乱を防ぎ、より直感的なフォーム操作を提供します。

JavaScriptでの設定項目
JavaScriptコードの冒頭部分
// == 設定ここから ==
から
// == 設定ここまで ==
の間)で、
ご自身のHTMLフォームに合わせて以下の各定数の値を設定してください。
  • checkboxGroupName
    : (必須)
    チェックボックス群の共通の
    name
    属性値を文字列で指定します。
    例:
    "interest_items"

  • otherCheckboxValue
    : (必須)
    「その他」にあたるチェックボックスの
    value
    属性値を文字列で指定します。
    例:
    "other"

    ※通常であれば、DBのマルチセレクトフィールドの選択肢のID値となります。

  • otherTextFieldName
    : (必須)
    「その他」選択時に活性化するテキスト入力フィールドの
    name
    属性値を文字列で指定します。
    例:
    "interest_other_text"

  • disabledClassName
    : (任意)
    テキストフィールドが非活性状態のときに適用するCSSクラス名を文字列で指定します。
    不要な場合は空文字
    ''
    にします。
    例:
    "disabled-field"

  • placeholderText
    : (任意)
    テキストフィールドが活性状態のときのプレースホルダーテキストを文字列で指定します。
    例:
    "具体的な内容を入力してください"

  • disabledPlaceholderText
    : (任意)
    テキストフィールドが非活性状態のときのプレースホルダーテキストを文字列で指定します。
    例:
    "「その他」を選択すると入力できます"

設定方法

以下の手順で設定を行います。

1. HTMLの記述
まず、フォーム内にチェックボックス群とテキスト入力フィールドを配置します。
以下は記述例です。
  <!--/* マルチセレクト(multiSelect) */-->
  <sp:input-field name="f06"></sp:input-field>
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      <th:block th:text="${fields['f06'].label}">
        Label
      </th:block>
      <span class="sp-form-required" th:if="${fields['f06'].required}" th:text="${fields['f06'].requiredIndicator}">*</span>
    </div>
    <div class="sp-form-data">
      <div class="sp-form-selection-vertical">
        <label class="sp-form-selection" th:each="option : ${fields['f06'].options}">
          <input type="checkbox" th:name="${fields['f06'].name}" th:value="${option.id}" th:checked="${inputs['f06'] != null ? #lists.contains(inputs['f06'], #strings.toString(option.id)) : false}">
          <span class="sp-form-selection-label" th:text="${option.label}">Item</span>
        </label>
      </div>
      <span class="sp-form-noted" th:if="${fields['f06'].help != null}" th:text="${fields['f06'].help}">Help text</span>
      <span class="sp-form-error" th:if="${errors['f06'] != null}" th:text="${errors['f06'].message}">Error message</span>
    </div>
  </div>

<-- 「その他」選択時のテキスト入力欄 -->
  <!--/* テキスト(text) */-->
  <sp:input-field name="f01"></sp:input-field>
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label">
      <th:block th:text="${fields['f01'].label}">
        Label
      </th:block>
      <span class="sp-form-required" th:if="${fields['f01'].required}" th:text="${fields['f01'].requiredIndicator}">*</span>
    </div>
    <div class="sp-form-data">
      <input type="text" class="sp-form-control" th:name="${fields['f01'].name}" th:placeholder="${fields['f01'].placeholder}" th:value="${inputs['f01']}" th:if="${fields['f01'].control == 'text'}">
      <!--ZipCode Option-->
      <div class="sp-form-zip-code" th:if="${fields['f01'].control == 'zipCode'}">
        <input type="text" class="sp-form-control" th:name="${fields['f01'].name}" th:placeholder="${fields['f01'].placeholder}" th:value="${inputs['f01']}">
        <button class="sp-form-zip-code-button" th:data-zipcode="|zipCodeSearch${fields['f01'].name}|" th:if="${fields['f01'].addressByZipCode != null}" th:text="${fields['f01'].zipCodeButtonLabel}">住所検索</button>
      </div>
      <span class="sp-form-noted" th:if="${fields['f01'].help != null}" th:text="${fields['f01'].help}">Help text</span>
      <span class="sp-form-error" th:data-zipcode="|zipCodeError${fields['f01'].name}|" th:text="${errors['f01']?.message}">Error message</span>
    </div>
  </div>
            
2. CSSの記述 (任意)
非活性時のテキスト入力フィールドに特定のスタイルを適用したい場合は、
JavaScriptコード内で指定するCSSクラス名(例:
disabled-field
)に対応するスタイルを別途定義してください。
以下はCSSの記述例です。
/* CSSの例 */
input[type="text"].disabled-field {
    background-color: #efefef;
    color: #777;
    cursor: not-allowed; /* 操作不可を視覚的に示す */
}
            
3. JavaScriptコードの記述
次に、上記のHTML要素を制御するJavaScriptコードです。
このコードをフォームブロックのJSタブに設置してください。
document.addEventListener('DOMContentLoaded', function() {
    // == 設定ここから ==
    const checkboxGroupName = "interest_items"; // (必須) チェックボックス群の共通のname属性値
    const otherCheckboxValue = "other";         // (必須) 「その他」にあたるチェックボックスのvalue属性値
    const otherTextFieldName = "interest_other_text"; // (必須) 「その他」選択時に活性化するテキスト入力フィールドのname属性値
    const disabledClassName = "disabled-field"; // (任意) 非活性時に適用するCSSクラス名 (不要なら空文字 '')
    const placeholderText = "具体的な内容を入力してください"; // (任意) 活性時のプレースホルダー
    const disabledPlaceholderText = "「その他」を選択すると入力できます"; // (任意) 非活性時のプレースホルダー
    // == 設定ここまで ==

    const otherTextField = document.getElementsByName(otherTextFieldName)[0];
    let otherCheckbox = null;

    const checkboxes = document.getElementsByName(checkboxGroupName);
    for (let i = 0; i < checkboxes.length; i++) {
        if (checkboxes[i].value === otherCheckboxValue) {
            otherCheckbox = checkboxes[i];
            break;
        }
    }

    if (!otherCheckbox) {
        console.error('「その他」のチェックボックスが見つかりません。value属性値「' + otherCheckboxValue + '」を持つ要素が name=\"' + checkboxGroupName + '\" のグループ内にあるか確認してください。');
        return;
    }
    if (!otherTextField) {
        console.error('「その他」のテキスト入力フィールドが見つかりません。name属性値「' + otherTextFieldName + '」を持つ要素を確認してください。');
        return;
    }

    function toggleOtherField() {
        if (otherCheckbox.checked) {
            otherTextField.readOnly = false;
            otherTextField.placeholder = placeholderText;
            if (disabledClassName) {
                otherTextField.classList.remove(disabledClassName);
            }
        } else {
            otherTextField.readOnly = true;
            otherTextField.value = ""; // 非選択時は入力内容をクリアする場合 (任意)
            otherTextField.placeholder = disabledPlaceholderText;
            if (disabledClassName) {
                otherTextField.classList.add(disabledClassName);
            }
        }
    }

    // 初期状態を設定
    toggleOtherField();

    // 「その他」チェックボックスの変更を監視
    otherCheckbox.addEventListener('change', toggleOtherField);
});

            
上記のJavaScriptコードの冒頭部分(
// == 設定ここから ==
から
// == 設定ここまで ==
の間)で、
ご自身のHTMLフォームに合わせて各
const
の値を設定してください。

特に、
checkboxGroupName
otherCheckboxValue
otherTextFieldName
は、
HTML要素の
name
属性や「その他」チェックボックスの
value
属性と正確に一致させる必要があります。

JavaScriptは、指定された
name
属性を持つすべてのチェックボックスを取得し、
その中から
value
otherCheckboxValue
と一致する「その他」チェックボックスを特定します。

そして、その「その他」チェックボックスのチェック状態(
checked
プロパティ)に応じてテキスト入力フィールドの活性/非活性を切り替えます。
イベントリスナーは「その他」チェックボックスの
change
イベントに設定されます。
4. 確認画面での表示制御
フォーム送信後、入力内容を確認画面などで表示する際に、
入力画面の条件に基づいて確認画面でも同様の表示/非表示を制御したい場合があります。
以下の確認画面のHTMLで表示/非表示を制御できます。
   <th:block th:if="${postParams['multiSelect'] != null AND (#lists.contains(postParams['multiSelect'], '3'))}">
    <!-- 表示させたいエリア -->
    <!--/* テキスト(text) */-->
  <div class="sp-form-item sp-form-field">
    <div class="sp-form-label" th:text="${fields['f01'].label}">
      Label
    </div>
    <div class="sp-form-data">
      <span class="sp-form-embedded" th:text="${values['f01']}">Example</span>
    </div>
  </div>
  </th:block>
            

実行結果

上記のHTMLとJavaScriptを組み合わせることで、ページが表示された際、
および「その他」チェックボックスの状態が変更されるたびに、
そのチェック状態に応じてテキスト入力欄が適切に活性化または非活性化されます。
「その他」チェックボックスがチェックされていれば入力可能に、
チェックされていなければ入力不可(
readonly
になり、指定されていればCSSクラスも適用される)状態になります。

まとめ

本記事では、JavaScriptを使用してチェックボックス群の中の「その他」の選択状態に応じて入力欄の状態を動的に変更する方法と、
Thymeleafを用いた確認画面での表示制御例を紹介しました。
この実装により、ユーザーが「その他」を選択した場合にのみ関連情報を入力させることができ、
フォームの使い勝手を向上させることができます。
このサンプルコードをベースに、実際の要件に合わせてカスタマイズしてみてください。

解決しない場合はこちら コンテンツに関しての
要望はこちら