毎日のように投稿ができるくらいにはエンジニアのお仕事に慣れてきたのかなと自惚れております金子です。

先日お仕事で、こんな感じのセレクトボックスを作成しました。

このセレクトボックス自体は、以下のURLにある通りjavascriptを使用すれば簡単に作成できるようです。

[JavaScript] 連動するセレクトボックス

こちらのやり方では、セレクトボックスの<option></option>に設定する項目はjsで作成した配列を使っているのですが、今回私はCakePHP側で作成した配列を使っていく必要がありました。PHPの配列をjsに渡すことなんてできるのか?と思ってググっていくとこちらの記事を発見。

PHPからJavaScriptに配列を渡す / Qiita@tksninoさん

この二つの記事の方法を使わせていただくことで、無事にPHPの配列をjsに渡し、連動する2つのセレクトボックスを作成することができました!

 

index.ctp

<head>
<!-- selectboxで使用する都道府県と市区町村のリストをphp→jsへ -->
  <?php
    if(isset($prefecture)){
     $prefJs=json_encode($prefecture);
    }else{
     $prefJs = [];
    } 
  ?>
  <?php
    if(isset($city)){
     $cityJs=json_encode($city);
    }else{
     $cityJs=[];
    }
  ?>
  <script type="text/javascript">
    //jsonをparseしてphpから受け取った配列をJavaScriptの変数に代入
    var pref_list=JSON.parse('<?php echo $prefJs; ?>');
    var city_list=JSON.parse('<?php echo $cityJs; ?>');
  </script>
  <?= $this->Html->script(['selectbox']) ?>
</head>
<body>
  <h2>市区町村の詳細ページを検索する</h2>
   <form name="searchCity">
      <select id="selectPref" onchange="selPref(this);"></select>
      <select id="selectCity" name="selectCity"></select>
      <button class="btn_wide_thick" type="button" onclick="return search(this);">検索</button>
   </form>
</body>

 

Controller

//phpからjsに渡す配列の形はこんなかんじです。
$prefecture = [
  0 => '都道府県を選択',
  1 => '北海道',
  2 => '東京都',
  3 => '愛知県'
];

//$cityの最初の階層が$prefectureのkeyと一致するようにしています。
//idというキーが市区町村固有のものとなっています。
$city = [
1 => [
  1 => [
    'id' => '',
    'name' => '市区町村を選択'
   ],
  2 => [
    'id' => '1',
    'name' => '函館市'
   ],
  3 => [
    'id' => '2',
    'name' => '札幌市'
   ]
 ],
2 => [
  1 => [
    'id' => '',
    'name' => '市区町村を選択'
   ],
  2 => [
    'id' => '3',
    'name' => '千代田区'
   ],
  3 => [
    'id' => '4',
    'name' => '足立区'
   ]
 ],
3 => [
  1 => [
    'id' => '',
    'name' => '市区町村を選択'
   ],
  2 => [
    'id' => '5',
    'name' => '名古屋市'
   ],
  3 => [
    'id' => '6',
    'name' => '豊田市'
   ]
 ],
];

 

selectbox.js

//都道府県リストの表示
window.onload=function(){
  for(var i=0;i<pref_list.length;i++){
    let op = document.createElement("option");
    op.value = i;
    op.text = pref_list[i];
    document.getElementById("selectPref").appendChild(op);
  }
}

//都道府県が選択されたら市区町村を設定
function selPref(obj){
  var targetArr = city_list[obj.value];
  var selObj = document.getElementById('selectCity');
  while(selObj.lastChild){
    selObj.removeChild(selObj.lastChild);
  }
  for(var i=0;i<targetArr.length;i++){
    let op = document.createElement("option");
    op.value = targetArr[i].id;
    op.text = targetArr[i].name;
    selObj.appendChild(op);
  }
}

//検索ボタンが押されたら、対象の市区町村詳細ページへリダイレクト
function search(){
	var element = document.getElementById("selectCity");
	var cityId = element.value; //選択された市町村のidを取得
	if(cityId == 0){ //市町村が未選択の場合
		return;
	}
	var url = 'http://'+location.host+'/city/detail/'+cityId;
	location.href = url; //「http://example.com/city/detail/市町村ID」にリダイレクト
}

以上です!

ここでのポイントは、selectbox.jsを読み込む前に「JSON.parse」してjsで使えるようにしたphp配列を作っておくこと、のようです。

ちなみに上でご紹介した記事を読む前に自分でほいほい作ったコードだと、
北海道を選んだあとに東京都を選びなおすと、2つ目のセレクトボックスの中身に北海道の市町村が残ったままになり、その後も都道府県を選びなおすとゾンビのように市町村が増えていく事態に陥っていました……。

今後も使う機会は出てきそうなので忘れないようにメモしておきます。ついでに他の方のお役に立てれば幸いです。

The following two tabs change content below.

金子風月

犬と歯車がついたものと跨り移動系スポーツ(馬・自転車)が好きな駆け出しweb系エンジニア。 2018年2月より、株式会社凛の皆様のおかげで憧れのweb系エンジニアになることができました。