質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.11%

動的な絞り込み検索機能(都道府県→市区町村)の実装を行いたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 604

anusama

score 7

前提・実現したいこと

Laravelで都道府県選択ができる機能を作っています。
動的な絞り込み検索機能の実装につまづいております。

実現したいことは、
都道府県を選び、それに合った市区町村が選択できるようになることです。
例:「東京都」→「新宿区や港区など」 がプルダウンで選択可能

参考ソース:[JavaScript] 連動するセレクトボックス
参考:https://teratail.com/questions/22207

発生している問題・エラーメッセージ

下記のコードで試したところ、
都道府県のプルダウンは問題なく選択できるのですが、
市区町村のプルダウンが反応しません(選択もできず、市区町村の候補も表れません)

該当のソースコード

blade.phpの一部記載

                        <div class="form-group">
                            <script>
                                var hoge = @json($prefectures);
                            </script>

                            {!! Form::label('storage_prefecture_id', '都道府県') !!}
                            <select name="storage_prefecture_id" class="form-control col-md-6" id="storage_prefecture_id">
                            @foreach($prefectures as $prefecture)
                                    <option value="{{ $prefecture->id }}">{{ $prefecture->name }}</option>
                            @endforeach
                            </select>

                            @if ($errors->has('storage_prefecture_id'))
                                {!! Form::label('storage_prefecture_id', $errors->first('storage_prefecture_id')) !!}
                            @endif
                        </div>

                        <div class="form-group">
                            <script>
                                var foo = @json($cities);
                            </script>

                            {!! Form::label('storage_storage_city_id', '市区町村') !!}
                            <select name="storage_city_id" class="form-control col-md-6" id="storage_city_id">
                                @foreach($cities as $city)
                                    <option value="{{ $city->id }}">{{ $city->name }}</option>
                                @endforeach
                            </select>

                            @if ($errors->has('storage_city_id'))
                                {!! Form::label('storage_city_id', $errors->first('storage_city_id')) !!}
                            @endif
                        </div>

app.jsの一部記載

var pref = hoge
console.table(pref)

var cit = foo
console.table(cit)


window.onload=function(){
  for(var i=0; i<pref.length; i++){
    let op = document.createElement("option");
    op.value = pref[i].id;
    op.text = pref[i].name;
    document.getElementById("storage_prefecture_id").appendChild(op);
  }
}

function awake_pref(obj){
  var targetPref;
  if(obj.value == "1"){
    targetPref = cit;
  }else if(obj.value == "2"){
    targetPref = cit;
  }else if(obj.value == "3"){
    targetPref = cit;
    |
   中略(obj.value == "4"~"47")
    |
  }else{
    targetPref = new Array();
  }
  var selObj = document.getElementById('storage_city_id');
  while(selObj.lastChild){
    selObj.removeChild(selObj.lastChild);
  }
  for(var i=0;i<targetPref.length;i++){
    let op = document.createElement("option");
    op.value = targetPref[i].id;
    op.text = targetPref[i].name;
    selObj.appendChild(op);
  }
}

var fuga = document.getElementById('storage_prefecture_id');
fuga.onchange = awake_pref(this);

DBには以下のようにデータが入っており、jsonで吐き出しております。
イメージ説明
イメージ説明

試したこと

多くの似たよなサンプルを探し、違うコードで試しましたが改善できませんでした。
プログラミング初学者のため、冗長かつ無駄なコードを書いており、
多分、prefecture_idを活用すべきだと思うのですが、行き詰まってしまいました。
一週間、色々試行錯誤しましたが一向に改善できないため、こちらの場でお力をお借りできればと思います。
お手数ですが、どうぞよろしくお願いいたします!

ご回答をいただき

このa, b, cはアロー関数を使用しない時、どのように扱えばよいのでしょうか。
また、書き方などに間違いがございましたら、ご指摘いただければ大変助かります。

const CREATE_OPTIONS = function(a, b) {
 a.innerText = '', [['選択してください',''],...b].forEach(function(c) {
  a.appendChild (new Option (...c))
});
}
const GET_PREFECTURES = function(a) {
 a.map(function(b) {
  return [b.name, b.id]
});
}
const GET_CITIES = function(a, b) {
 a.filter(function(c) {
  return c.prefecture_id === b;
});
}
const SEARCH_ID = function(a) {
 document.querySelector(a);
}

window.onload = function () {
 CREATE_OPTIONS (SEARCH_ID ('#storage_prefecture_id'), GET_PREFECTURES(pref));
 SEARCH_ID ('#storage_prefecture_id').onchange =
  ({target:a}) => CREATE_OPTIONS(SEARCH_ID ('#storage_city_id'),GET_PREFECTURES(GET_CITIES(cit, parseInt(a.value,10))));
};
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

const CREATE_OPTIONS = function (target, ary) {
  var first = [['選択してください','']];

  target.innerText = '';
  ary = first.concat (ary);

  for (var i = 0, I = ary.length; i < I; i += 1) {
    var text = ary[i][0];
    var val  = ary[i][1];
    var opt = new Option (text, val);
    target.appendChild (opt);
  }
};


const GET_PREFECTURES = function (ary) {
  var rst = [ ];

  for (var i = 0, I = ary.length; i < I; i += 1) {
    var text = ary[i].name;
    var val  = ary[i].id;
    rst.push ([text, val]);
  }

  return rst;
}


const GET_CITIES = function (ary, id) {
  var rst = [ ];

  for (var i = 0, I = ary.length; i < I; i += 1) {
    if (ary[i].prefecture_id === id) {
      rst.push (ary[i]);
    }
  }

  return rst;
};


const SEARCH_ID = function(a) {
  return document.querySelector(a);
};


window.onload = function () {

  CREATE_OPTIONS (SEARCH_ID ('#storage_prefecture_id'), GET_PREFECTURES (pref));

  SEARCH_ID ('#storage_prefecture_id').onchange = function (event) {
    var select = event.target;
    var id = parseInt (select.value, 10);

    CREATE_OPTIONS(
      SEARCH_ID ('#storage_city_id'),
      GET_PREFECTURES (GET_CITIES (cit, id))
    );
  };
};

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

const
  A = (a, b)=> (a.innerText= '', [['--',''],...b].forEach (c => a.appendChild (new Option (...c)))),
  B = a => a.map (b=> [b.name, b.id]),
  D = (a, b) => a.filter (c=> c.prefecture_id == b),
  $$ = a => document.querySelector (a);

window.onload = function () {
  A ($$ ('#storage_prefecture_id'), B(pref));
  $$ ('#storage_prefecture_id').onchange =
    ({target:a}) => A($$ ('#storage_city_id'),B(D(cit, parseInt (a.value,10))));
};

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/11 23:16 編集

    ご回答いただき、大変ありがとうございます。
    示していただいたコードで無事動かせることができました。

    hai_haiさんのコードですが、
    JavaScriptの知識が未だ浅い私には少し難しいところがあり、
    未だ全ての理解に至っておりません。

    自身で噛み砕き短縮形を戻す作業を行ったところ
    a, b, c の理解が及びませんでした。
    こちらは変数宣言などはしなくてよいのでしょうか。
    「ご回答をいただき」に記載した私のコードですと、望んだ動きはしてくれない状況にあります。

    お忙しいとこと、大変恐縮ではありますが、
    後学のためにご教授いただければ幸いです。

    キャンセル

  • 2019/03/12 13:28

    hai_hai様
    再回答、ありがとうございます!

    先程、書き下しコードを読み大方理解することができました。
    私のレベルに合わせ、非常に丁寧に記載いただき本当にありがとうございます。
    40行が10行程のコードに短縮可能であることに驚いたのと、自身の力不足を実感しました。

    再三になりますが、良い学びをご提供いただき、ありがとうございました!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる