連動プルダウンを作ろう
<input type="select" id="select1">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</input>
<input type="select" id="select2">
<option value="a1">a1</option>
<option value="a2">a2</option>
<option value="b1">b1</option>
<option value="b2">b2</option>
<option value="c1">c1</option>
<option value="c2">c2</option>
</input>
こんなよくあるselect1の動きに追従してselect2のoptionの中身を変えようというプルダウン。
jQueryを書こう
$('#select1').on('change', evt => {
$('select2').find('option').each((idx, elem) => {
if($(elem).val().indexOf($(evt.target).val()) != -1){
// ①オプションを表示する
} else {
// ②オプションを非表示にする
}
});
});
select1の選択されたvalueとselect2のoptionのvalueをeachで一個ずつ比較して表示・非表示を行うというやつ。
簡単簡単はいできたーと書いたのがこのコード
$('#select1').on('change', evt => {
$('select2').find('option').each((idx, elem) => {
if($(elem).val().indexOf($(evt.target).val()) != -1){
// ①オプションを表示する
$(elem).show();
} else {
// ②オプションを非表示にする
$(elem).hide();
}
});
});
動作確認をしよう
先ほど書いたコード、、、え?safari動かなくね?
調べてみた
。。。残念ながらsafari, IEでoptionのshow()/hide()は効かないらしい。。。
つまりdisplay: noneが適用できない。
そのほかにも、内側の要素にはshow()/hide()が効かないという報告の記事もあり(未検証)
代替案
1、非表示はremove()、表示はappend()/prepend()する
2、prop("disabled", true)で選択できなくする
3、都度検索してキャッシュやDBなどからoption全部を入れ替える
今回は1で実装
<label id="hidden_area" style="display:none"></label>
1,このlabelに一度要素を退避。
2,退避したoptionに対してeach。
3,select1のvalueに一致するoptionのみ元のselect2へprepend()する
の手順を踏む。
最終的なコード
$('#select1').on('change', evt => {
let val = $('#select1').val();
// 全て退避
$('select2').find('option').each((idx, elem) => {
$('#hidden_area').prepend(elem);
});
$('#hidden_area').find('option').each((idx, elem) => {
if($(elem).val().indexOf(val) != -1){
// オプションをselect2へ移動
$('#select2').prepend(elem);
}
});
});
ようやく動いた。。。
1度前に遭遇したことあったのだが、ハマるのが2度目だったのでメモ。。。。