非同期通信(Ajax)を使わず、セレクトボックスのリストを動的に変更する

はじめに

開発をしている際に、以下のような要件が出てきました。

①セレクトボックスを3つ使う(以下ボックスA、ボックスB、ボックスC)。
②ボックスA以外のセレクトボックスのリストは最初は空。
③ボックスAを変更したらボックスBのリストを変更
④ボックスBを変更したらボックスCのリストを変更
⑤これらはフォーム内で用い、サブミット時バリデーションエラーに引っかかれば、入力項目そのままでフォーム画面に戻る。

最初は「動的に変更するなら、それぞれにchangeイベント設定してAjaxで値取ってきてリストにしてぶち込めばいいな。簡単じゃん。」と思っていましたが、⑤があることでこの安易な考えは打ち砕かれました。

⑤を実際に実行してみると、フォームの値は持って帰ってきてくれますが、適用するリスト項目がないので、もちろん何も選択してくれません。

つまり、各セレクトボックスには最初からすべてのリストを持たせておく必要があるが、ユーザーから見て動的にリストが変更されるようにしなくてはならない。

私が至った結論は、とりあえず初期のリストは全部持たせて後からJavaScriptで見えないようにすればいいのでは?といったものでした。

実践

問題のソースです。
今回はボックス2つ想定で話を進めていこうと思います。(3つにしたところで同じような処理が増えるだけなので)
ボックスAのA-1を選んだら、ボックスBのdata-id=”1″の項目のみがリストに表示されるといった法則で実装をしたい。

<label>ボックスA</label>
<select name="boxA" id="boxA">
  <option>選択してください</option>
  <option value="1">A-1</option>
  <option value="2">A-2</option>
  <option value="3">A-3</option>
</select>

<label>ボックスB</label>
<select name="boxB" id="boxB">
  <option>選択してください</option>
  <option value="1" data-id="1">B-1</option>
  <option value="2" data-id="1">B-2</option>
  <option value="3" data-id="2">B-3</option>
  <option value="4" data-id="2">B-4</option>
  <option value="5" data-id="3">B-5</option>
  <option value="6" data-id="3">B-6</option>
</select>

まず「見えないようにする」で思いついたのがCSSの「display:none」です。
そこでjqueryの「hide()」「show()」を使ってみようと思いました。

// まずBを全部非表示にする
$('#boxB option[data-id]').hide();

$('#boxA').change(function () {
  // Aが変更されるときに一度非表示にする
  $('#boxB option[data-id]').hide();
  // Aのvalueに対応するBのdata-idのoptionを表示する
  $("#boxB option[data-id='"+ $('#boxA').val() +"']").show();
});

結論として、うまくいきました!

…IEを除いては。
WEBエンジニア最大の敵ですね。。。というわけでこの方法は除外です。

続けて調査を進めていると、「optionタグをspanタグなどでラップしてしまえば非表示になる」という記事を見つけました。

<span><option value="1" data-id="1">B-1</option></span>

早速上記のようにしてみたところ、IEでも非表示になることが確認できました。
最終的に以下のように実装をしてみました。

// まずBを非表示にする
$('#boxB > option[data-id]').wrap('<span>');

$('#boxA').change(function () {
  // Aが変更されるときに一度非表示にする
  $('#boxB > option[data-id]').wrap('<span>');
  // Aのvalueに対応するBのdata-idのoptionを表示する
  $("#boxB option[data-id='"+ $('#boxA').val() +"']").unwrap();
});

うまくいきました!
ただし、セレクタを間違えるとoptionタグにspanタグが多重で付いてしまう可能性があるので、気を付けるようにしてください。

まとめ

今まで「動的に値を変える=Ajax」という頭でしたが、違う観点で考えるきっかけができてよかったと思います。
また、セレクタの使い方やカスタムデータ属性などについても、実際に使う機会ができて有意義な内容でした。


--------------------------
システム開発のご要望・ご相談はこちらから

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です