kame's engineer note

技術関連のメモをブログに記録していく

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を変更することができる。