railsで部分にajaxを使う selectbox編
概要
selectboxの内容をajaxで動的に変更したいとき用のメモ。
AとBの2つのselectboxがあるとして、Aのselectboxで値を選択したら、それに連動した値の一覧をBのselectboxに反映するといった動作だ。
例としてAを都道府県、Bを市区町村とする。
これらはhas_manyの関係とする。
都道府県(prefecture) ==has_many=⇛ 市区町村(city)
簡単に流れをまとめると
1. jqueryで都道府県のselectboxが変更されたことを探知して、$.get
メソッドでajaxのactionを選択された都道府県idのparameterを渡して呼び出す。
2. ajax actionで都道府県idを基に市区町村をデータを取得する。
3. javascriptで上記で取得した市区町村データをselectboxに反映する。
formを作成
controller.rb
def new @form = Form.new @cities = City.none end
new.html.slim
javascript: $(window).load(function(){ var prefecture_select = $('[data-role="prefecture_select"]'); var url = "#{ajax_path}"; prefecture_select.change(function(){ $.get(url, {prefecture_id: prefecture_select.has('option:selected').val()}); }); }); div = form_for(@form, url:form_path) do |f| .div p= label :prefecture p= collection_select :prefecture,:prefecture_id, Prefecture.all, :id, :name,{selected: @prefecture_id.presence || 0,prompt: true},{'data-role'=>'prefecture_select'} .div p= f.label :city_id p= f.select :city_id, @cities,{prompt: true},{'data-role'=>'city_select'} .div = f.submit "登録"
今回はdata属性からDOM要素を取得するようにしている。
ajaxでselectboxの内容を変更
new.html.slim
javascript: $(window).load(function(){ var prefecture_select = $('[data-role="prefecture_select"]'); var url = "#{ajax_path}"; prefecture_select.change(function(){ $.get(url, {prefecture_id: prefecture_select.has('option:selected').val()}); }); });
jsでは、都道府県のselectboxが変更されたら、次に記述するajaxのaction宛に$.get
を実行する。
その際にparameterに市区町村のselectboxで選択された値を指定する。
controller.rb
def ajax @form = Form.new @cities = City.where(prefecture_id: params[:prefecture_id]) end
contoller内にajax actionを記述。
ajax actionでは、受け取ったparameterを基にselectboxで使用する市区町村オブジェクトを取得する。
ajax.js.slim
| $('[data-role="city_select"]').html("#{escape_javascript(options_for_select(@cities.map{|c| [c.name,c.id]}))}");
html()
でhtmlの書き換えを行う。
ajaxのactionで取得した市区町村データをoptions_for_select()
で都道府県のselectboxの値を更新する。
その際にselectboxで使えるようにobjectからmapを使って配列に変換してあげる。
また、action実行時にhtmlデータがない場合はjsが実行されるが、 下記のように明示的に記述しても良い。
respond_to do |format| format.js end
以上でajaxを使って動的にselectboxを変更することができる。