JqueryでSELECTの選択肢を自由に変化させる
JqueryでHTMLを流動的に書き換えることはよくあります。
実際にエラーメッセージ等を出力する場合等に重宝します。
今回、JqueryでHTMLの書き換えを実装することになったのですが、書き換えるのはSELECTフォームの選択肢です。
具体的には、SELECTフォームが2つあり、一つ目の選択内容によって、2つ目のSELECTフォームの選択肢を変化させるというものです。
EC-CUBEでよくあるやつです。
やればできることですが、どうやればいいの?
状態でした。
いろいろググり、試行錯誤して実装できましたので、忘備録として記録いたします。
今回やりたいこと
サンプルを見ていただければ一目瞭然ですが、大項目の選択によって、小項目の選択肢が変化します。
今回のソースはこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title>セレクトで値を切り替える</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script> $(document).ready(function() { // (2)選択肢テーブル // 色テーブル var color_table = [ {value: "red", label: "赤"}, {value: "blue", label: "青"}, {value: "yellow", label: "黄"}, {value: "pink", label: "桃"}, {value: "green", label: "緑"} ] // サイズテーブル var size_table = [ {value: "small", label: "小さい"}, {value: "normal", label: "普通"}, {value: "big", label: "大きい"} ] // (3)大項目が変化した場合に発火 $("[name=syubetu]").change(function() { // 選択した値を取得 var select_value = $(this).val(); // (4)現在の小項目を初期化 // 2番目のセレクトを初期化 $("[name=sub]").children().remove(); if (select_value == 1) // 色指定 ? { // (5)選択肢をセット // 色テーブルをセット color_table.forEach( function(table) { $("[name=sub]").append($("<option>").attr({ value: table.value}).text(table.label)); }); } else if (select_value == 2) // サイズ指定 { // サイズテーブルをセット size_table.forEach( function(table) { $("[name=sub]").append($("<option>").attr({ value: table.value}).text(table.label)); }); } }); }); </script> <style type="text/css"> .box { padding: 20px; width: 400px; margin-right: auto; margin-left: auto; } section { padding: 10px; margin-bottom: 20px; border: 1px solid #ccc; } p { margin: 0px; } select { font-size: 18px; padding: 10px; } </style> </head> <body> <div class="box"> <p>大項目を選択すると小項目の値が変わります</p> <!-- (1)SELECTフォーム部分 --> <section> <p>大項目</p> <select name="syubetu"> <option value="">大項目を選択してください</option> <option value="1">色</option> <option value="2">大きさ</option> </select> </section> <section> <p>小項目</p> <select name="sub"> </select> </section> </div> </body> </html> |
例のごとくまとめてみると何のことかわからないので、分解して考えます。
(1)SELECTフォーム部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<section> <p>大項目</p> <select name="syubetu"> <option value="">大項目を選択してください</option> <option value="1">色</option> <option value="2">大きさ</option> </select> </section> <section> <p>小項目</p> <select name="sub"> </select> </section> |
セレクトフォーム部分は、通常の記載と同じです。
違う部分は、小項目の選択肢(option)が1つも記述がありません。
これは、Jqueryで後から付け足すため記述する必要がないのです。
(2)選択肢テーブル部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 色テーブル var color_table = [ {value: "red", label: "赤"}, {value: "blue", label: "青"}, {value: "yellow", label: "黄"}, {value: "pink", label: "桃"}, {value: "green", label: "緑"} ] // サイズテーブル var size_table = [ {value: "small", label: "小さい"}, {value: "normal", label: "普通"}, {value: "big", label: "大きい"} ] |
選択肢を付け足すには、後述しますがJqueryのappend()を使用します。
ただ、汎用性を高めるため、事前に選択肢を配列化しました。
Javascriptの二次配列については、こちらをご参考ください。
(3)大項目が変化した場合に発火する部分
1 2 3 4 |
$("[name=syubetu]").change(function() { }); |
大項目が変化したら、小項目の内容を書き換えるので、大項目が変化したタイミングを検知しなければいけません。
それがこの部分です。
Jqueryの change()関数は、指定項目の値が変化したら発火します。
(4)現在の小項目を初期化する
1 2 |
// 2番目のセレクトを初期化 $("[name=sub]").children().remove(); |
大項目が確定したら、小項目の中身をいったんクリアする必要があります。
なぜならば、クリアしなければどんどん追加されてしまうからです。
今回は全削除ですが、個別削除も可能です。
例えば「赤」を消す場合は次のように記述します。
1 |
$("[name=sub]").children("[value=red]").remove(); |
(5)選択肢を追加する
1 2 3 4 5 |
// 色テーブルをセット color_table.forEach( function(table) { $("[name=sub]").append($("<option>").attr({ value: table.value}).text(table.label)); }); |
Jqueryのappend()で小項目に選択肢を追加しています。
今回の最も肝心な部分です。
仕掛けは、(2)のテーブルをループさせ、テーブルの値の数だけ追加しています。
forEachは、配列をループさせる命令です。PHP等にはない記述方法なのでわかりにくいですが、foreach文と似ています。
appendは、タグをダイレクトに記述する方法もありますが、配列の値をセットすることを考えたら、分解してセットするやり方のほうがわかりやすかったです。
append部分は、共通で使えるためサブルーチン化してもOKです。
試しにサブルーチンかしてみたら、うまくいきました。
今回悩んだこと
今回は複数の事象についてどうすればいいのか悩みました。
それがこちらです。
- SELECTの選択肢をその都度書き換えるにはどうすればいいのか?
- その選択肢を配列化しておくことはできるのか?
- 大項目選択時に、どの小項目テーブルを使用すればよいか区別をつけることができるのか?
難問が複数同時に来ると、パニックになってしまいがちです。
なので私は今回は頭からひとつづつ問題点を解決してゆきました。
3回解決したら完成していました。
千里の道も一歩からといいますが、難問も千個に分解すれば簡単な問題の集合体です。
パニックになる前に、地道に一つずつ解決してゆくことが結果的に近道です。