ホームページ制作 オフィスオバタ

JqueryでSELECTの選択肢を自由に変化させる

JqueryでHTMLを流動的に書き換えることはよくあります。
実際にエラーメッセージ等を出力する場合等に重宝します。

今回、JqueryでHTMLの書き換えを実装することになったのですが、書き換えるのはSELECTフォームの選択肢です。

具体的には、SELECTフォームが2つあり、一つ目の選択内容によって、2つ目のSELECTフォームの選択肢を変化させるというものです。

EC-CUBEでよくあるやつです。

やればできることですが、どうやればいいの?
状態でした。

いろいろググり、試行錯誤して実装できましたので、忘備録として記録いたします。

今回やりたいこと

実際にできたものがこちらです。

サンプルを見ていただければ一目瞭然ですが、大項目の選択によって、小項目の選択肢が変化します。

今回のソースはこちら


<!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フォーム部分

<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)選択肢テーブル部分

	// 色テーブル
	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)大項目が変化した場合に発火する部分

$("[name=syubetu]").change(function()
{
});

大項目が変化したら、小項目の内容を書き換えるので、大項目が変化したタイミングを検知しなければいけません。

それがこの部分です。

Jqueryの change()関数は、指定項目の値が変化したら発火します。

(4)現在の小項目を初期化する

// 2番目のセレクトを初期化
$("[name=sub]").children().remove();

大項目が確定したら、小項目の中身をいったんクリアする必要があります。
なぜならば、クリアしなければどんどん追加されてしまうからです。

今回は全削除ですが、個別削除も可能です。
例えば「赤」を消す場合は次のように記述します。

$("[name=sub]").children("[value=red]").remove();

(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です。
試しにサブルーチンかしてみたら、うまくいきました。

今回悩んだこと

今回は複数の事象についてどうすればいいのか悩みました。
それがこちらです。

  1. SELECTの選択肢をその都度書き換えるにはどうすればいいのか?
  2. その選択肢を配列化しておくことはできるのか?
  3. 大項目選択時に、どの小項目テーブルを使用すればよいか区別をつけることができるのか?

難問が複数同時に来ると、パニックになってしまいがちです。
なので私は今回は頭からひとつづつ問題点を解決してゆきました。

3回解決したら完成していました。

千里の道も一歩からといいますが、難問も千個に分解すれば簡単な問題の集合体です。
パニックになる前に、地道に一つずつ解決してゆくことが結果的に近道です。

モバイルバージョンを終了