デモ(動画)
やりたいこと
上記のGIF通り、
カテゴリーが選択されたと同時に、親カテゴリーに紐づく子カテゴリーが出てくるようにしたい。
入れ子構造については以下を参照
【追記予定】awesome_nested_setを使った入れ子構造のDB設計
## 実装概要
jQueryのajaxメソッドを使って、カテゴリーが選択されたら子カテゴリーがappendされるようにした。
## コード
routing
route.rb
Rails.application.routes.draw do
root 'products#new'
resources :products, only: [:create] do
<!-- 今回はsearchアクションをajaxメソッドで叩きます-->
collection do
get 'search'
end
end
end
view
new.html.haml
= form_for @product do |f|
= f.label :name
= f.text_field :name, placeholder: "商品名を入力"
#cat
= f.select :category_id, Category.roots.map {|i| ["#{i.name}", i.id]}, { selected: @product.category_id, include_blank: true }, {id: "l_category"}
js
category.js
$(document).on('turbolinks:load', function() {
// selectを追加するHTML
var cat_seach = $("#cat");
function appendSelect(catNum) {
if(catNum == 1) {
var select_id = `m_category`
} else if(catNum == 2) {
var select_id = `s_category`
}
var html =
`<select name="product[category_id]" id="${select_id}">
<option value>---</option>
</select>`
cat_seach.append(html)
}
// optionを追加するHTML
function appendCat(catOption, catNum) {
if (catNum == 1) {
var appendId = $("#m_category")
} else if (catNum == 2) {
var appendId = $("#s_category")
}
appendId.append(
$("<option>")
.val($(catOption).attr('id'))
.text($(catOption).attr('name'))
)
}
// Lカテゴリーが選択された時のアクション
$("#l_category").on('change', function() {
l_cat = $(this).val()
$("#m_category, #s_category").remove()
// ajaxでリクエストを送信
$.ajax({
type: "GET",
url: "/products/search",
data: {l_cat: l_cat},
dataType: 'json'
})
// doneメソッドでappendする
.done(function(m_cat) {
var catNum = 1
appendSelect(catNum)
m_cat.forEach(function(m_cat) {
appendCat(m_cat, catNum)
})
})
})
// Mカテゴリーが選択された時のアクション
$(document).on('change', "#m_category", function() {
m_cat = $(this).val()
$("#s_category").remove()
$.ajax({
type: "GET",
url: "/products/search",
data: {m_cat: m_cat},
dataType: 'json'
})
.done(function(s_cat) {
var catNum = 2
appendSelect(catNum)
s_cat.forEach(function(s_cat) {
appendCat(s_cat, catNum)
})
})
})
})
controller
categories_controller.rb
<!--関係ないアクションは省略しています-->
def search
if params[:l_cat]
@m_cat = Category.find(params[:l_cat]).children
else
@s_cat = Category.find(params[:m_cat]).children
end
respond_to do |format|
format.html
format.json
end
end
jbuilder
search.json.jbuilder
json.array! @m_cat do |m_cat|
json.id m_cat.id
json.name m_cat.name
end
json.array! @s_cat do |s_cat|
json.id s_cat.id
json.name s_cat.name
end
勉強になったところ
optionタグの追加の方法
optionの追加
$("#m_category").append(
$("<option>")
.val($(m_cat).attr('id'))
.text($(m_cat).attr('name'))
)
}
こういう風に書くことで、selectタグのoptionが追加できることを知りました。
始めはselectを追加すればいいじゃん!と思ってましたが、配列形式で渡ってくるため、配列の中身分selectが増えてしまい、上手な方法が浮かばなかったので、こちらの方法にしました。
参考記事
・jQuery でセレクトボックスのプルダウン項目(option 要素)を追加/削除する方法
https://webllica.com/jquery-select-option-add-del/