【JavaScript】同じデータを使用する複数のセレクトボックスで重複選択を防止する

同じデータを使って、複数のセレクトボックスからユーザーにそれぞれ選択して貰う場合。

例えば、第1希望・第2希望・第3希望を選んでもらうというような感じです。

そんな時に、第1希望で選択した値が第2希望では選択できなくなっていると、ユーザーは使いやすいのではないかと。

それを実現するための、JavaScriptです。

まずはフォームを用意する

まずはセレクトボックスを必要なだけ用意します。

実装はWordPressで行ったので、詳しい作り方は過去の記事をご覧いただければと。

カスタムフィールドの値でのセレクトボックスの作り方ですが。

投稿データを利用してつくるのは基本的には変わりません。

重複選択を防ぐJavaScript

最初にJavaScript部分の全文を載せてしまいますね。

//ページが読み込まれたらセレクトボックスの情報を取得する
document.addEventListener('DOMContentLoaded', function() {
    const selects = document.querySelectorAll('.yourfun-select');
    
    // 選択された値を追跡する関数
    function updateSelections(changedSelect) {
        const selectedValues = Array.from(selects).map(select => select.value);
        
        // 各セレクトボックスの選択肢を更新
        selects.forEach((select, index) => {
            if (select !== changedSelect) {
                Array.from(select.options).forEach(option => {
                    if (option.value === '') return; // 初期値は無視
                    
                    // 他のセレクトボックスで選択されている値は無効化
                    if (selectedValues.includes(option.value) && option.value !== select.value) {
                        option.disabled = true;
                    } else {
                        option.disabled = false;
                    }
                });
            }
        });
    }
    
    // 初期状態の更新
    updateSelections();
    
    // 変更イベントのリスナーを追加
    selects.forEach(select => {
        select.addEventListener('change', function() {
            updateSelections(this);
        });
    });
});

二行目の「.yourfun-select」部分を、JavaScriptを適用したいセレクトボックスのクラス名に変更すれば、動作すると思います。

少し実装を急いだコードなので、他の環境でテストはできてないのですが。

今のところ特に問題は起きてないので、大丈夫でしょう!

外部のJSファイルを作成したり、<script></script>で囲って直書きすれば使えます。

JavaScriptの動作の内容

簡単にですが説明を残しておきます。

1行目:DomContentLoaded

まずは、ページが読み込まれたあとに、セレクトボックスの情報を取得します。

その時に使用するのが、DomContentLoadedです。

ここで設定したクラス名を使い、該当のセレクトボックスの情報を取得します。

参考:Document: DOMContentLoaded イベント ‐ mdn web docs

6行目:updateSelections(changedSelect)関数

ここから、セレクトボックスで選択された値を追跡し、選択されていた場合は選択できなくなるような処理を行います。

選択前の初期値は省き、データの中で選択された値を読み取り、disabled属性を切り替えます。

変更があったセレクトボックスはchangedSelectで判定され、他のセレクトボックスの選択肢を更新します。

32行目:addEventlistenerで関数を呼び出す

29行目までがupdateSelectionsの関数の定義です。

この後に、セレクトボックスの値が変わった時にupdateSelectionsを呼び出したいので。

動作するようにaddEventListenerで設定します。

参考:EventTarget: addEventListener() メソッド ‐ mdn web docs

これで、1つ目のセレクトボックスで選んだ値は、2つ目以降のセレクトボックスでは選択できなくなります。

UI改善のひと手間

実装したプログラムのセレクトボックスの値が多かったので。

もし選択したい値の近くのと押し間違えて、選択が間違っていることに気付かない・・・

となると、かなりストレスだよなぁと。

そんなことを思いながら書いたコードです。

UI/UXを追い求めるとキリがないですがー。

こういった一手間が大事なんですよね。