[jQuery]selectの組み合わせによって選択不可のoptionを設定する方法

ちょっと凝ったフォームに、とか。

動作イメージ

こんなのがあったとする。

<select name="select01">
    <option value="option01">option01</option>
    <option value="option02">option02</option>
    <option value="option03">option03</option>
    <option value="option04">option04</option>
</select>
<select name="select02">
    <option value="option01">option01</option>
    <option value="option02">option02</option>
    <option value="option03">option03</option>
    <option value="option04">option04</option>
</select>

select01でoption04を選んだ場合、select02で選択不可のoptionが発生する。

<select name="select01">
    <option value="option01">option01</option>
    <option value="option02">option02</option>
    <option value="option03">option03</option>
    <option value="option04" selected>option04</option>
</select>
<select name="select02">
    <option value="option01">option01</option>
    <option value="option02">option02</option>
    <option value="option03" disabled>option03</option>
    <option value="option04" disabled>option04</option>
</select>

select02選択後にselect01を操作すると、selectedとdisabledが共存するoptionが生まれる。

仕様上、selectedのoptionにdisabledを付与したとしてもselectedは維持される。

その場合は初期化(選択可能なoptionの一番上を選択)する。

やりましょう

こんなかんじ

$(function () {
    const $select01 = $('select[name="select01"]');
    const $select02 = $('select[name="select02"]');

    // select01のvalueごとに、select02で無効にするvalueを定義
    const disableMap = {
        'option03': ['option03'],
        'option04': ['option03', 'option04'],
    };

    $select01.on('change', function () {
        const val01 = $(this).val();
        const val02 = $select02.val();

        // 今回の選択に対する無効対象一覧(なければ空配列)
        const currentDisabledValues = disableMap[val01] || [];

        // 全optionを走査して、有効・無効を切り替え
        $select02.find('option').each(function () {
            const $opt = $(this);
            const optVal = $opt.val();
            $opt.prop('disabled', currentDisabledValues.includes(optVal));
        });

        // 無効化対象が選ばれていたら、有効なoptionに切り替える
        if (currentDisabledValues.includes(val02)) {
            const $firstEnabled = $select02.find('option:not([disabled])').first();
            if ($firstEnabled.length) {
                $select02.val($firstEnabled.val());
            }
        }
    });

    // ページ読み込み時に初期化したい場合(省略可)
    $select01.trigger('change');
});

select2つの組み合わせを配列にまとめたので汎用性が地味にある。

文字数だけで言えば変数化したり配列化したりしないほうがだいぶ抑えられるし、規模によってはそっちの方が軽そうに見えたりもする。

コメント

タイトルとURLをコピーしました